aboutsummaryrefslogtreecommitdiff
path: root/alacritty/src/display
diff options
context:
space:
mode:
authorKirill Chibisov <contact@kchibisov.com>2025-01-11 08:47:32 +0300
committerGitHub <noreply@github.com>2025-01-11 08:47:32 +0300
commitcd884c984bbd6a7c65965681083da61e091ff7e5 (patch)
tree013ee3133480b90d3ca8455962997b24574e4659 /alacritty/src/display
parent28910e3adc9d48edc4f43008d987eecd869ded31 (diff)
downloadr-alacritty-cd884c984bbd6a7c65965681083da61e091ff7e5.tar.gz
r-alacritty-cd884c984bbd6a7c65965681083da61e091ff7e5.tar.bz2
r-alacritty-cd884c984bbd6a7c65965681083da61e091ff7e5.zip
Try to recover from GPU resets
Use context robustness to get notified about GPU resets and try to recover from them by rebuilding the rendering pipeline.
Diffstat (limited to 'alacritty/src/display')
-rw-r--r--alacritty/src/display/mod.rs61
1 files changed, 56 insertions, 5 deletions
diff --git a/alacritty/src/display/mod.rs b/alacritty/src/display/mod.rs
index 6c685a2a..9f11ccf6 100644
--- a/alacritty/src/display/mod.rs
+++ b/alacritty/src/display/mod.rs
@@ -8,7 +8,10 @@ use std::num::NonZeroU32;
use std::ops::{Deref, DerefMut};
use std::time::{Duration, Instant};
+use glutin::config::GetGlConfig;
use glutin::context::{NotCurrentContext, PossiblyCurrentContext};
+use glutin::display::GetGlDisplay;
+use glutin::error::ErrorKind;
use glutin::prelude::*;
use glutin::surface::{Surface, SwapInterval, WindowSurface};
@@ -33,6 +36,7 @@ use alacritty_terminal::term::{
};
use alacritty_terminal::vte::ansi::{CursorShape, NamedColor};
+use crate::config::debug::RendererPreference;
use crate::config::font::Font;
use crate::config::window::Dimensions;
#[cfg(not(windows))]
@@ -49,7 +53,7 @@ use crate::display::window::Window;
use crate::event::{Event, EventType, Mouse, SearchState};
use crate::message_bar::{MessageBuffer, MessageType};
use crate::renderer::rects::{RenderLine, RenderLines, RenderRect};
-use crate::renderer::{self, GlyphCache, Renderer};
+use crate::renderer::{self, platform, GlyphCache, Renderer};
use crate::scheduler::{Scheduler, TimerId, Topic};
use crate::string::{ShortenDirection, StrShortener};
@@ -385,6 +389,7 @@ pub struct Display {
hint_mouse_point: Option<Point>,
renderer: ManuallyDrop<Renderer>,
+ renderer_preference: Option<RendererPreference>,
surface: ManuallyDrop<Surface<WindowSurface>>,
@@ -421,7 +426,7 @@ impl Display {
}
// Create the GL surface to draw into.
- let surface = renderer::platform::create_gl_surface(
+ let surface = platform::create_gl_surface(
&gl_context,
window.inner_size(),
window.raw_window_handle(),
@@ -513,6 +518,7 @@ impl Display {
context: ManuallyDrop::new(Replaceable::new(context)),
visual_bell: VisualBell::from(&config.bell),
renderer: ManuallyDrop::new(renderer),
+ renderer_preference: config.debug.renderer,
surface: ManuallyDrop::new(surface),
colors: List::from(&config.colors),
frame_timer: FrameTimer::new(),
@@ -552,10 +558,55 @@ impl Display {
}
}
- pub fn make_current(&self) {
- if !self.context.get().is_current() {
- self.context.make_current(&self.surface).expect("failed to make context current")
+ pub fn make_current(&mut self) {
+ let is_current = self.context.get().is_current();
+
+ // Attempt to make the context current if it's not.
+ let context_loss = if is_current {
+ self.renderer.was_context_reset()
+ } else {
+ match self.context.make_current(&self.surface) {
+ Err(err) if err.error_kind() == ErrorKind::ContextLost => {
+ info!("Context lost for window {:?}", self.window.id());
+ true
+ },
+ _ => false,
+ }
+ };
+
+ if !context_loss {
+ return;
+ }
+
+ let gl_display = self.context.display();
+ let gl_config = self.context.config();
+ let raw_window_handle = Some(self.window.raw_window_handle());
+ let context = platform::create_gl_context(&gl_display, &gl_config, raw_window_handle)
+ .expect("failed to recreate context.");
+
+ // Drop the old context and renderer.
+ unsafe {
+ ManuallyDrop::drop(&mut self.renderer);
+ ManuallyDrop::drop(&mut self.context);
}
+
+ // Activate new context.
+ let context = context.treat_as_possibly_current();
+ self.context = ManuallyDrop::new(Replaceable::new(context));
+ self.context.make_current(&self.surface).expect("failed to reativate context after reset.");
+
+ // Recreate renderer.
+ let renderer = Renderer::new(&self.context, self.renderer_preference)
+ .expect("failed to recreate renderer after reset");
+ self.renderer = ManuallyDrop::new(renderer);
+
+ // Resize the renderer.
+ self.renderer.resize(&self.size_info);
+
+ self.reset_glyph_cache();
+ self.damage_tracker.frame().mark_fully_damaged();
+
+ debug!("Recovered window {:?} from gpu reset", self.window.id());
}
fn swap_buffers(&self) {