From 9b694fcc547f664ed0fecdd5c84c067d7d3e7f14 Mon Sep 17 00:00:00 2001 From: trimental Date: Mon, 24 Sep 2018 00:21:47 +0800 Subject: [PATCH] Fix mesa rendering outside window borders on wayland The mesa workaround has lead to some issues with rendering on Wayland. To resolve this problem, the mesa workaround has been restructured in a way which still allows clearing the screen before rendering without killing performance with the mesa driver. The performance is identical to the master brach and there have been no recorded regressions. --- CHANGELOG.md | 1 + src/display.rs | 52 +++++++++++++++++++++++--------------------------- src/main.rs | 15 ++++++++------- 3 files changed, 33 insertions(+), 35 deletions(-) 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.