mirror of
https://github.com/alacritty/alacritty.git
synced 2024-11-11 13:51:01 -05:00
Fix flickering during resize on Wayland
This also fixes an issue of windows not being rendered while resizing. Fixes #6069.
This commit is contained in:
parent
6dc670cde0
commit
90552e3e7f
7 changed files with 81 additions and 34 deletions
|
@ -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
|
- Bottom gap for certain builtin box drawing characters
|
||||||
- Incorrect built-in glyphs for `U+2567` and `U+2568`
|
- Incorrect built-in glyphs for `U+2567` and `U+2568`
|
||||||
- Character mappings in the DEC special graphics character set (line drawing)
|
- Character mappings in the DEC special graphics character set (line drawing)
|
||||||
|
- Window flickering on resize on Wayland
|
||||||
|
|
||||||
## 0.10.1
|
## 0.10.1
|
||||||
|
|
||||||
|
|
|
@ -237,7 +237,7 @@ pub struct WindowIdentity {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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) {
|
pub fn override_identity_config(&self, identity: &mut Identity) {
|
||||||
if let Some(title) = &self.title {
|
if let Some(title) = &self.title {
|
||||||
identity.title = title.clone();
|
identity.title = title.clone();
|
||||||
|
|
|
@ -359,6 +359,9 @@ pub struct Display {
|
||||||
/// Unprocessed display updates.
|
/// Unprocessed display updates.
|
||||||
pub pending_update: DisplayUpdate,
|
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,
|
is_damage_supported: bool,
|
||||||
debug_damage: bool,
|
debug_damage: bool,
|
||||||
damage_rects: Vec<DamageRect>,
|
damage_rects: Vec<DamageRect>,
|
||||||
|
@ -367,6 +370,19 @@ pub struct Display {
|
||||||
meter: Meter,
|
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 {
|
impl Display {
|
||||||
pub fn new<E>(
|
pub fn new<E>(
|
||||||
config: &UiConfig,
|
config: &UiConfig,
|
||||||
|
@ -425,7 +441,7 @@ impl Display {
|
||||||
// If the scaling factor changed update the glyph cache and mark for resize.
|
// 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 should_resize = (estimated_scale_factor - window.scale_factor).abs() > f64::EPSILON;
|
||||||
let (cell_width, cell_height) = if should_resize {
|
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 {
|
} else {
|
||||||
(cell_width, cell_height)
|
(cell_width, cell_height)
|
||||||
};
|
};
|
||||||
|
@ -433,7 +449,7 @@ impl Display {
|
||||||
// Load font common glyphs to accelerate rendering.
|
// Load font common glyphs to accelerate rendering.
|
||||||
debug!("Filling glyph cache with common glyphs");
|
debug!("Filling glyph cache with common glyphs");
|
||||||
renderer.with_loader(|mut api| {
|
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) {
|
if let Some(dimensions) = dimensions.filter(|_| should_resize) {
|
||||||
|
@ -520,6 +536,7 @@ impl Display {
|
||||||
visual_bell: VisualBell::from(&config.bell),
|
visual_bell: VisualBell::from(&config.bell),
|
||||||
colors: List::from(&config.colors),
|
colors: List::from(&config.colors),
|
||||||
pending_update: Default::default(),
|
pending_update: Default::default(),
|
||||||
|
pending_renderer_update: Default::default(),
|
||||||
is_damage_supported,
|
is_damage_supported,
|
||||||
debug_damage,
|
debug_damage,
|
||||||
damage_rects,
|
damage_rects,
|
||||||
|
@ -529,30 +546,31 @@ impl Display {
|
||||||
/// Update font size and cell dimensions.
|
/// Update font size and cell dimensions.
|
||||||
///
|
///
|
||||||
/// This will return a tuple of the cell width and height.
|
/// This will return a tuple of the cell width and height.
|
||||||
fn update_glyph_cache(
|
fn update_font_size(
|
||||||
renderer: &mut Renderer,
|
|
||||||
glyph_cache: &mut GlyphCache,
|
glyph_cache: &mut GlyphCache,
|
||||||
scale_factor: f64,
|
scale_factor: f64,
|
||||||
config: &UiConfig,
|
config: &UiConfig,
|
||||||
font: &Font,
|
font: &Font,
|
||||||
) -> (f32, f32) {
|
) -> (f32, f32) {
|
||||||
renderer.with_loader(|mut api| {
|
let _ = glyph_cache.update_font_size(font, scale_factor);
|
||||||
let _ = glyph_cache.update_font_size(font, scale_factor, &mut api);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Compute new cell sizes.
|
// Compute new cell sizes.
|
||||||
compute_cell_size(config, &glyph_cache.font_metrics())
|
compute_cell_size(config, &glyph_cache.font_metrics())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clear glyph cache.
|
/// Reset glyph cache.
|
||||||
fn clear_glyph_cache(&mut self) {
|
fn reset_glyph_cache(&mut self) {
|
||||||
let cache = &mut self.glyph_cache;
|
let cache = &mut self.glyph_cache;
|
||||||
self.renderer.with_loader(|mut api| {
|
self.renderer.with_loader(|mut api| {
|
||||||
cache.clear_glyph_cache(&mut api);
|
cache.reset_glyph_cache(&mut api);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Process update events.
|
/// 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>(
|
pub fn handle_update<T>(
|
||||||
&mut self,
|
&mut self,
|
||||||
terminal: &mut Term<T>,
|
terminal: &mut Term<T>,
|
||||||
|
@ -568,31 +586,29 @@ impl Display {
|
||||||
let (mut cell_width, mut cell_height) =
|
let (mut cell_width, mut cell_height) =
|
||||||
(self.size_info.cell_width(), self.size_info.cell_height());
|
(self.size_info.cell_width(), self.size_info.cell_height());
|
||||||
|
|
||||||
// Ensure we're modifying the correct OpenGL context.
|
if pending_update.font().is_some() || pending_update.cursor_dirty() {
|
||||||
self.window.make_current();
|
let renderer_update = self.pending_renderer_update.get_or_insert(Default::default());
|
||||||
|
renderer_update.clear_font_cache = true
|
||||||
|
}
|
||||||
|
|
||||||
// Update font size and cell dimensions.
|
// Update font size and cell dimensions.
|
||||||
if let Some(font) = pending_update.font() {
|
if let Some(font) = pending_update.font() {
|
||||||
let scale_factor = self.window.scale_factor;
|
let scale_factor = self.window.scale_factor;
|
||||||
let cell_dimensions = Self::update_glyph_cache(
|
let cell_dimensions =
|
||||||
&mut self.renderer,
|
Self::update_font_size(&mut self.glyph_cache, scale_factor, config, font);
|
||||||
&mut self.glyph_cache,
|
|
||||||
scale_factor,
|
|
||||||
config,
|
|
||||||
font,
|
|
||||||
);
|
|
||||||
cell_width = cell_dimensions.0;
|
cell_width = cell_dimensions.0;
|
||||||
cell_height = cell_dimensions.1;
|
cell_height = cell_dimensions.1;
|
||||||
|
|
||||||
info!("Cell size: {} x {}", cell_width, cell_height);
|
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());
|
let (mut width, mut height) = (self.size_info.width(), self.size_info.height());
|
||||||
if let Some(dimensions) = pending_update.dimensions() {
|
if let Some(dimensions) = pending_update.dimensions() {
|
||||||
width = dimensions.width as f32;
|
width = dimensions.width as f32;
|
||||||
height = dimensions.height 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);
|
let padding = config.window.padding(self.window.scale_factor);
|
||||||
|
@ -618,10 +634,36 @@ impl Display {
|
||||||
|
|
||||||
// Resize terminal.
|
// Resize terminal.
|
||||||
terminal.resize(self.size_info);
|
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.
|
// Resize renderer.
|
||||||
let physical = PhysicalSize::new(self.size_info.width() as _, self.size_info.height() as _);
|
if renderer_update.resize {
|
||||||
self.window.resize(physical);
|
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);
|
self.renderer.resize(&self.size_info);
|
||||||
|
|
||||||
if self.collect_damage() {
|
if self.collect_damage() {
|
||||||
|
|
|
@ -463,7 +463,7 @@ pub struct TextShaderProgram {
|
||||||
///
|
///
|
||||||
/// If GL_EXT_blend_func_extended is not available, the rendering is split into 4 passes.
|
/// 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
|
/// 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.
|
/// Rendering is split into three passes.
|
||||||
u_rendering_pass: GLint,
|
u_rendering_pass: GLint,
|
||||||
|
|
|
@ -264,19 +264,22 @@ impl GlyphCache {
|
||||||
loader.load_glyph(&glyph)
|
loader.load_glyph(&glyph)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clear currently cached data in both GL and the registry.
|
/// Reset currently cached data in both GL and the registry to default state.
|
||||||
pub fn clear_glyph_cache<L: LoadGlyph>(&mut self, loader: &mut L) {
|
pub fn reset_glyph_cache<L: LoadGlyph>(&mut self, loader: &mut L) {
|
||||||
loader.clear();
|
loader.clear();
|
||||||
self.cache = HashMap::default();
|
self.cache = Default::default();
|
||||||
|
|
||||||
self.load_common_glyphs(loader);
|
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,
|
&mut self,
|
||||||
font: &Font,
|
font: &Font,
|
||||||
scale_factor: f64,
|
scale_factor: f64,
|
||||||
loader: &mut L,
|
|
||||||
) -> Result<(), crossfont::Error> {
|
) -> Result<(), crossfont::Error> {
|
||||||
// Update dpi scaling.
|
// Update dpi scaling.
|
||||||
self.rasterizer.update_dpr(scale_factor as f32);
|
self.rasterizer.update_dpr(scale_factor as f32);
|
||||||
|
@ -304,8 +307,6 @@ impl GlyphCache {
|
||||||
self.metrics = metrics;
|
self.metrics = metrics;
|
||||||
self.builtin_box_drawing = font.builtin_box_drawing;
|
self.builtin_box_drawing = font.builtin_box_drawing;
|
||||||
|
|
||||||
self.clear_glyph_cache(loader);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -325,6 +325,9 @@ impl WindowContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.dirty {
|
if self.dirty {
|
||||||
|
// Force the display to process any pending display update.
|
||||||
|
self.display.process_renderer_update();
|
||||||
|
|
||||||
self.dirty = false;
|
self.dirty = false;
|
||||||
|
|
||||||
// Request immediate re-draw if visual bell animation is not finished yet.
|
// Request immediate re-draw if visual bell animation is not finished yet.
|
||||||
|
|
|
@ -20,8 +20,8 @@ pub struct Rgb {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rgb {
|
impl Rgb {
|
||||||
/// Implementation of W3C's luminance algorithm:
|
/// Implementation of W3C's luminance
|
||||||
/// https://www.w3.org/TR/WCAG20/#relativeluminancedef
|
/// [algorithm](https://www.w3.org/TR/WCAG20/#relativeluminancedef)
|
||||||
fn luminance(self) -> f64 {
|
fn luminance(self) -> f64 {
|
||||||
let channel_luminance = |channel| {
|
let channel_luminance = |channel| {
|
||||||
let channel = channel as f64 / 255.;
|
let channel = channel as f64 / 255.;
|
||||||
|
|
Loading…
Reference in a new issue