diff --git a/CHANGELOG.md b/CHANGELOG.md index c251ec61..38ead29b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- 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 4c3ffed1..928434d8 100644 --- a/src/display.rs +++ b/src/display.rs @@ -25,6 +25,7 @@ use font::{self, Rasterize}; use meter::Meter; use renderer::{self, GlyphCache, QuadRenderer}; use term::{Term, SizeInfo}; +use sync::FairMutex; use window::{self, Size, Pixels, Window, SetInnerSize}; @@ -97,7 +98,6 @@ pub struct Display { meter: Meter, font_size: font::Size, size_info: SizeInfo, - last_background_color: Rgb, } /// Can wakeup the render loop from other threads @@ -210,7 +210,6 @@ impl Display { meter: Meter::new(), font_size: font::Size::new(0.), size_info, - last_background_color: background_color, }) } @@ -325,7 +324,29 @@ impl Display { /// A reference to Term whose state is being drawn must be provided. /// /// This call may block if vsync is enabled - pub fn draw(&mut self, mut terminal: MutexGuard, config: &Config) { + pub fn draw(&mut self, terminal: &FairMutex, 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(); + // Clear dirty flag terminal.dirty = !terminal.visual_bell.completed(); @@ -345,13 +366,6 @@ impl Display { } } - let size_info = *terminal.size_info(); - let visual_bell_intensity = terminal.visual_bell.intensity(); - - let background_color = terminal.background_color(); - let background_color_changed = background_color != self.last_background_color; - self.last_background_color = background_color; - { let glyph_cache = &mut self.glyph_cache; @@ -366,11 +380,6 @@ impl Display { // mutable borrow let window_focused = self.window.is_focused; self.renderer.with_api(config, &size_info, visual_bell_intensity, |mut api| { - // Clear screen to update whole background with new color - if background_color_changed { - api.clear(background_color); - } - // Draw the grid api.render_cells( terminal.renderable_cells(config, window_focused), @@ -394,19 +403,6 @@ impl Display { self.window .swap_buffers() .expect("swap buffers"); - - // Clear after swap_buffers 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. - self.renderer.with_api(config, &size_info, visual_bell_intensity, |api| { - api.clear(background_color); - }); } pub fn get_window_id(&self) -> Option { diff --git a/src/main.rs b/src/main.rs index 0888c9b5..03a372df 100644 --- a/src/main.rs +++ b/src/main.rs @@ -173,7 +173,7 @@ fn run(mut config: Config, options: &cli::Options) -> Result<(), Box> { // Main display loop loop { // Process input and window events - let mut terminal = processor.process_events(&terminal, display.window()); + let mut terminal_lock = processor.process_events(&terminal, display.window()); // Handle config reloads if let Some(new_config) = config_monitor @@ -183,22 +183,23 @@ fn run(mut config: Config, options: &cli::Options) -> Result<(), Box> { config = new_config.update_dynamic_title(options); display.update_config(&config); processor.update_config(&config); - terminal.update_config(&config); - terminal.dirty = true; + terminal_lock.update_config(&config); + terminal_lock.dirty = true; } // Maybe draw the terminal - if terminal.needs_draw() { + if terminal_lock.needs_draw() { // Try to update the position of the input method editor - display.update_ime_position(&terminal); + display.update_ime_position(&terminal_lock); // Handle pending resize events // // The second argument is a list of types that want to be notified // of display size changes. - display.handle_resize(&mut terminal, &config, &mut [&mut pty, &mut processor]); + display.handle_resize(&mut terminal_lock, &config, &mut [&mut pty, &mut processor]); + drop(terminal_lock); // Draw the current state of the terminal - display.draw(terminal, &config); + display.draw(&terminal, &config); } // Begin shutdown if the flag was raised.