aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKirill Chibisov <contact@kchibisov.com>2022-06-09 19:31:08 +0300
committerGitHub <noreply@github.com>2022-06-09 16:31:08 +0000
commit90552e3e7f8f085919a39435a8a68b3a2f633e54 (patch)
tree711534a54f813a8aad9fe2c3015478ba5ad03d31
parent6dc670cde0c136e28c71d4ebe67c5c8bb9df65b1 (diff)
downloadalacritty-90552e3e7f8f085919a39435a8a68b3a2f633e54.tar.gz
alacritty-90552e3e7f8f085919a39435a8a68b3a2f633e54.zip
Fix flickering during resize on Wayland
This also fixes an issue of windows not being rendered while resizing. Fixes #6069.
-rw-r--r--CHANGELOG.md1
-rw-r--r--alacritty/src/cli.rs2
-rw-r--r--alacritty/src/display/mod.rs88
-rw-r--r--alacritty/src/renderer/text/gles2.rs2
-rw-r--r--alacritty/src/renderer/text/glyph_cache.rs15
-rw-r--r--alacritty/src/window_context.rs3
-rw-r--r--alacritty_terminal/src/term/color.rs4
7 files changed, 81 insertions, 34 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 69d28921..46a9d77b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -38,6 +38,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Bottom gap for certain builtin box drawing characters
- Incorrect built-in glyphs for `U+2567` and `U+2568`
- Character mappings in the DEC special graphics character set (line drawing)
+- Window flickering on resize on Wayland
## 0.10.1
diff --git a/alacritty/src/cli.rs b/alacritty/src/cli.rs
index 3c64458b..83b317b9 100644
--- a/alacritty/src/cli.rs
+++ b/alacritty/src/cli.rs
@@ -237,7 +237,7 @@ pub struct WindowIdentity {
}
impl WindowIdentity {
- /// Override the [`WindowIdentityConfig`]'s fields with the [`WindowOptions`].
+ /// Override the [`WindowIdentity`]'s fields with the [`WindowOptions`].
pub fn override_identity_config(&self, identity: &mut Identity) {
if let Some(title) = &self.title {
identity.title = title.clone();
diff --git a/alacritty/src/display/mod.rs b/alacritty/src/display/mod.rs
index eb7b8d53..99df511f 100644
--- a/alacritty/src/display/mod.rs
+++ b/alacritty/src/display/mod.rs
@@ -359,6 +359,9 @@ pub struct Display {
/// Unprocessed display updates.
pub pending_update: DisplayUpdate,
+ /// The renderer update that takes place only once before the actual rendering.
+ pub pending_renderer_update: Option<RendererUpdate>,
+
is_damage_supported: bool,
debug_damage: bool,
damage_rects: Vec<DamageRect>,
@@ -367,6 +370,19 @@ pub struct Display {
meter: Meter,
}
+/// Pending renderer updates.
+///
+/// All renderer updates are cached to be applied just before rendering, to avoid platform-specific
+/// rendering issues.
+#[derive(Debug, Default, Copy, Clone)]
+pub struct RendererUpdate {
+ /// Should resize the window.
+ resize: bool,
+
+ /// Clear font caches.
+ clear_font_cache: bool,
+}
+
impl Display {
pub fn new<E>(
config: &UiConfig,
@@ -425,7 +441,7 @@ impl Display {
// If the scaling factor changed update the glyph cache and mark for resize.
let should_resize = (estimated_scale_factor - window.scale_factor).abs() > f64::EPSILON;
let (cell_width, cell_height) = if should_resize {
- Self::update_glyph_cache(&mut renderer, &mut glyph_cache, scale_factor, config, font)
+ Self::update_font_size(&mut glyph_cache, scale_factor, config, font)
} else {
(cell_width, cell_height)
};
@@ -433,7 +449,7 @@ impl Display {
// Load font common glyphs to accelerate rendering.
debug!("Filling glyph cache with common glyphs");
renderer.with_loader(|mut api| {
- glyph_cache.load_common_glyphs(&mut api);
+ glyph_cache.reset_glyph_cache(&mut api);
});
if let Some(dimensions) = dimensions.filter(|_| should_resize) {
@@ -520,6 +536,7 @@ impl Display {
visual_bell: VisualBell::from(&config.bell),
colors: List::from(&config.colors),
pending_update: Default::default(),
+ pending_renderer_update: Default::default(),
is_damage_supported,
debug_damage,
damage_rects,
@@ -529,30 +546,31 @@ impl Display {
/// Update font size and cell dimensions.
///
/// This will return a tuple of the cell width and height.
- fn update_glyph_cache(
- renderer: &mut Renderer,
+ fn update_font_size(
glyph_cache: &mut GlyphCache,
scale_factor: f64,
config: &UiConfig,
font: &Font,
) -> (f32, f32) {
- renderer.with_loader(|mut api| {
- let _ = glyph_cache.update_font_size(font, scale_factor, &mut api);
- });
+ let _ = glyph_cache.update_font_size(font, scale_factor);
// Compute new cell sizes.
compute_cell_size(config, &glyph_cache.font_metrics())
}
- /// Clear glyph cache.
- fn clear_glyph_cache(&mut self) {
+ /// Reset glyph cache.
+ fn reset_glyph_cache(&mut self) {
let cache = &mut self.glyph_cache;
self.renderer.with_loader(|mut api| {
- cache.clear_glyph_cache(&mut api);
+ cache.reset_glyph_cache(&mut api);
});
}
/// Process update events.
+ ///
+ /// XXX: this function must not call to any `OpenGL` related tasks. Only logical update
+ /// of the state is being performed here. Rendering update takes part right before the
+ /// actual rendering.
pub fn handle_update<T>(
&mut self,
terminal: &mut Term<T>,
@@ -568,31 +586,29 @@ impl Display {
let (mut cell_width, mut cell_height) =
(self.size_info.cell_width(), self.size_info.cell_height());
- // Ensure we're modifying the correct OpenGL context.
- self.window.make_current();
+ if pending_update.font().is_some() || pending_update.cursor_dirty() {
+ let renderer_update = self.pending_renderer_update.get_or_insert(Default::default());
+ renderer_update.clear_font_cache = true
+ }
// Update font size and cell dimensions.
if let Some(font) = pending_update.font() {
let scale_factor = self.window.scale_factor;
- let cell_dimensions = Self::update_glyph_cache(
- &mut self.renderer,
- &mut self.glyph_cache,
- scale_factor,
- config,
- font,
- );
+ let cell_dimensions =
+ Self::update_font_size(&mut self.glyph_cache, scale_factor, config, font);
cell_width = cell_dimensions.0;
cell_height = cell_dimensions.1;
info!("Cell size: {} x {}", cell_width, cell_height);
- } else if pending_update.cursor_dirty() {
- self.clear_glyph_cache();
}
let (mut width, mut height) = (self.size_info.width(), self.size_info.height());
if let Some(dimensions) = pending_update.dimensions() {
width = dimensions.width as f32;
height = dimensions.height as f32;
+
+ let renderer_update = self.pending_renderer_update.get_or_insert(Default::default());
+ renderer_update.resize = true
}
let padding = config.window.padding(self.window.scale_factor);
@@ -618,10 +634,36 @@ impl Display {
// Resize terminal.
terminal.resize(self.size_info);
+ }
+
+ /// Update the state of the renderer.
+ ///
+ /// NOTE: The update to the renderer is split from the display update on purpose, since
+ /// on some platforms, like Wayland, resize and other OpenGL operations must be performed
+ /// right before rendering, otherwise they could lock the back buffer resulting in
+ /// rendering with the buffer of old size.
+ ///
+ /// This also resolves any flickering, since the resize is now synced with frame callbacks.
+ pub fn process_renderer_update(&mut self) {
+ let renderer_update = match self.pending_renderer_update.take() {
+ Some(renderer_update) => renderer_update,
+ _ => return,
+ };
// Resize renderer.
- let physical = PhysicalSize::new(self.size_info.width() as _, self.size_info.height() as _);
- self.window.resize(physical);
+ if renderer_update.resize {
+ let physical =
+ PhysicalSize::new(self.size_info.width() as _, self.size_info.height() as _);
+ self.window.resize(physical);
+ }
+
+ // Ensure we're modifying the correct OpenGL context.
+ self.window.make_current();
+
+ if renderer_update.clear_font_cache {
+ self.reset_glyph_cache();
+ }
+
self.renderer.resize(&self.size_info);
if self.collect_damage() {
diff --git a/alacritty/src/renderer/text/gles2.rs b/alacritty/src/renderer/text/gles2.rs
index 32aaa173..01470813 100644
--- a/alacritty/src/renderer/text/gles2.rs
+++ b/alacritty/src/renderer/text/gles2.rs
@@ -463,7 +463,7 @@ pub struct TextShaderProgram {
///
/// If GL_EXT_blend_func_extended is not available, the rendering is split into 4 passes.
/// One is used for the background and the rest to perform subpixel text rendering according to
- /// https://github.com/servo/webrender/blob/master/webrender/doc/text-rendering.md.
+ /// <https://github.com/servo/webrender/blob/master/webrender/doc/text-rendering.md>.
///
/// Rendering is split into three passes.
u_rendering_pass: GLint,
diff --git a/alacritty/src/renderer/text/glyph_cache.rs b/alacritty/src/renderer/text/glyph_cache.rs
index b57b10b7..72415900 100644
--- a/alacritty/src/renderer/text/glyph_cache.rs
+++ b/alacritty/src/renderer/text/glyph_cache.rs
@@ -264,19 +264,22 @@ impl GlyphCache {
loader.load_glyph(&glyph)
}
- /// Clear currently cached data in both GL and the registry.
- pub fn clear_glyph_cache<L: LoadGlyph>(&mut self, loader: &mut L) {
+ /// Reset currently cached data in both GL and the registry to default state.
+ pub fn reset_glyph_cache<L: LoadGlyph>(&mut self, loader: &mut L) {
loader.clear();
- self.cache = HashMap::default();
+ self.cache = Default::default();
self.load_common_glyphs(loader);
}
- pub fn update_font_size<L: LoadGlyph>(
+ /// Update the inner font size.
+ ///
+ /// NOTE: To reload the renderers's fonts [`Self::reset_glyph_cache`] should be called
+ /// afterwards.
+ pub fn update_font_size(
&mut self,
font: &Font,
scale_factor: f64,
- loader: &mut L,
) -> Result<(), crossfont::Error> {
// Update dpi scaling.
self.rasterizer.update_dpr(scale_factor as f32);
@@ -304,8 +307,6 @@ impl GlyphCache {
self.metrics = metrics;
self.builtin_box_drawing = font.builtin_box_drawing;
- self.clear_glyph_cache(loader);
-
Ok(())
}
diff --git a/alacritty/src/window_context.rs b/alacritty/src/window_context.rs
index 6ead6e4e..f04a8e04 100644
--- a/alacritty/src/window_context.rs
+++ b/alacritty/src/window_context.rs
@@ -325,6 +325,9 @@ impl WindowContext {
}
if self.dirty {
+ // Force the display to process any pending display update.
+ self.display.process_renderer_update();
+
self.dirty = false;
// Request immediate re-draw if visual bell animation is not finished yet.
diff --git a/alacritty_terminal/src/term/color.rs b/alacritty_terminal/src/term/color.rs
index a9494e7a..1cfdec6b 100644
--- a/alacritty_terminal/src/term/color.rs
+++ b/alacritty_terminal/src/term/color.rs
@@ -20,8 +20,8 @@ pub struct Rgb {
}
impl Rgb {
- /// Implementation of W3C's luminance algorithm:
- /// https://www.w3.org/TR/WCAG20/#relativeluminancedef
+ /// Implementation of W3C's luminance
+ /// [algorithm](https://www.w3.org/TR/WCAG20/#relativeluminancedef)
fn luminance(self) -> f64 {
let channel_luminance = |channel| {
let channel = channel as f64 / 255.;