Commit b22999f1 authored by trimental's avatar trimental Committed by Christian Duerr

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.
parent f785f88a
...@@ -37,6 +37,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ...@@ -37,6 +37,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed ### Fixed
- Rendering now occurs without the terminal locked which improves performance
- Clear screen properly before rendering of content to prevent various graphical glitches - Clear screen properly before rendering of content to prevent various graphical glitches
- Fix build failure on 32-bit systems - Fix build failure on 32-bit systems
- Windows started as unfocused now show the hollow cursor if the setting is enabled - Windows started as unfocused now show the hollow cursor if the setting is enabled
......
...@@ -24,7 +24,7 @@ use config::Config; ...@@ -24,7 +24,7 @@ use config::Config;
use font::{self, Rasterize}; use font::{self, Rasterize};
use meter::Meter; use meter::Meter;
use renderer::{self, GlyphCache, QuadRenderer}; use renderer::{self, GlyphCache, QuadRenderer};
use term::{Term, SizeInfo}; use term::{Term, SizeInfo, RenderableCell};
use sync::FairMutex; use sync::FairMutex;
use window::{self, Size, Pixels, Window, SetInnerSize}; use window::{self, Size, Pixels, Window, SetInnerSize};
...@@ -325,27 +325,15 @@ impl Display { ...@@ -325,27 +325,15 @@ impl Display {
/// ///
/// This call may block if vsync is enabled /// This call may block if vsync is enabled
pub fn draw(&mut self, terminal: &FairMutex<Term>, config: &Config) { 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 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 // Clear dirty flag
terminal.dirty = !terminal.visual_bell.completed(); terminal.dirty = !terminal.visual_bell.completed();
...@@ -366,6 +354,21 @@ impl Display { ...@@ -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; let glyph_cache = &mut self.glyph_cache;
...@@ -373,18 +376,9 @@ impl Display { ...@@ -373,18 +376,9 @@ impl Display {
{ {
let _sampler = self.meter.sampler(); 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| { self.renderer.with_api(config, &size_info, visual_bell_intensity, |mut api| {
// Draw the grid // Draw the grid
api.render_cells( api.render_cells(grid_cells.iter(), glyph_cache);
terminal.renderable_cells(config, window_focused),
glyph_cache,
);
}); });
} }
...@@ -398,8 +392,6 @@ impl Display { ...@@ -398,8 +392,6 @@ impl Display {
} }
} }
// Unlock the terminal mutex; following call to swap_buffers() may block
drop(terminal);
self.window self.window
.swap_buffers() .swap_buffers()
.expect("swap buffers"); .expect("swap buffers");
...@@ -423,3 +415,4 @@ impl Display { ...@@ -423,3 +415,4 @@ impl Display {
self.window().set_ime_spot(nspot_x, nspot_y); self.window().set_ime_spot(nspot_x, nspot_y);
} }
} }
...@@ -374,7 +374,7 @@ pub struct RenderApi<'a> { ...@@ -374,7 +374,7 @@ pub struct RenderApi<'a> {
current_atlas: &'a mut usize, current_atlas: &'a mut usize,
program: &'a mut ShaderProgram, program: &'a mut ShaderProgram,
config: &'a Config, config: &'a Config,
visual_bell_intensity: f32 visual_bell_intensity: f32,
} }
#[derive(Debug)] #[derive(Debug)]
...@@ -799,7 +799,7 @@ impl<'a> RenderApi<'a> { ...@@ -799,7 +799,7 @@ impl<'a> RenderApi<'a> {
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
self.render_cells(cells.into_iter(), glyph_cache); self.render_cells(cells.iter(), glyph_cache);
} }
#[inline] #[inline]
...@@ -817,12 +817,12 @@ impl<'a> RenderApi<'a> { ...@@ -817,12 +817,12 @@ impl<'a> RenderApi<'a> {
} }
} }
pub fn render_cells<I>( pub fn render_cells<'b, I>(
&mut self, &mut self,
cells: I, cells: I,
glyph_cache: &mut GlyphCache glyph_cache: &mut GlyphCache
) )
where I: Iterator<Item=RenderableCell> where I: Iterator<Item=&'b RenderableCell>
{ {
for cell in cells { for cell in cells {
// Get font key for cell // Get font key for cell
......
...@@ -372,6 +372,7 @@ impl<'a> RenderableCellsIter<'a> { ...@@ -372,6 +372,7 @@ impl<'a> RenderableCellsIter<'a> {
} }
} }
#[derive(Debug)]
pub struct RenderableCell { pub struct RenderableCell {
/// A _Display_ line (not necessarily an _Active_ line) /// A _Display_ line (not necessarily an _Active_ line)
pub line: Line, pub line: Line,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment