diff --git a/wezterm/src/gui/termwindow.rs b/wezterm/src/gui/termwindow.rs index e23fd812f..c3188fc5c 100644 --- a/wezterm/src/gui/termwindow.rs +++ b/wezterm/src/gui/termwindow.rs @@ -723,7 +723,54 @@ impl WindowCallbacks for TermWindow { } fn paint_opengl(&mut self, frame: &mut glium::Frame) { - self.paint_opengl_pass(frame, 0); + self.check_for_config_reload(); + let config = configuration(); + let start = std::time::Instant::now(); + + { + let palette = self.palette(); + let background_alpha = (config.window_background_opacity * 255.0) as u8; + let background = rgbcolor_alpha_to_window_color(palette.background, background_alpha); + + let (r, g, b, a) = background.to_tuple_rgba(); + frame.clear_color_srgb(r, g, b, a); + } + + for pass in 0.. { + match self.paint_opengl_pass(frame) { + Ok(_) => break, + Err(err) => { + if let Some(&OutOfTextureSpace { size: Some(size) }) = + err.downcast_ref::() + { + let result = if pass == 0 { + // Let's try clearing out the atlas and trying again + self.render_state.clear_texture_atlas(&self.render_metrics) + } else { + log::error!("grow texture atlas to {}", size); + self.recreate_texture_atlas(Some(size)) + }; + + if let Err(err) = result { + log::error!( + "Failed to {} texture: {}", + if pass == 0 { "clear" } else { "resize" }, + err + ); + break; + } + } else { + log::error!("paint_opengl_pass failed: {}", err); + break; + } + } + } + } + + self.call_draw(frame).ok(); + log::debug!("paint_pane_opengl elapsed={:?}", start.elapsed()); + metrics::value!("gui.paint.opengl", start.elapsed()); + self.update_title(); } } @@ -2310,31 +2357,17 @@ impl TermWindow { Ok(()) } - fn paint_opengl_pass(&mut self, frame: &mut glium::Frame, pass: usize) { + fn paint_opengl_pass(&mut self, frame: &mut glium::Frame) -> anyhow::Result<()> { let panes = self.get_panes_to_render(); if panes.is_empty() { frame.clear_color_srgb(0., 0., 0., 1.); - return; - } - - self.check_for_config_reload(); - let config = configuration(); - - let start = std::time::Instant::now(); - - { - let palette = self.palette(); - let background_alpha = (config.window_background_opacity * 255.0) as u8; - let background = rgbcolor_alpha_to_window_color(palette.background, background_alpha); - - let (r, g, b, a) = background.to_tuple_rgba(); - frame.clear_color_srgb(r, g, b, a); + return Ok(()); } if let Some(pane) = self.get_active_pane_or_overlay() { let splits = self.get_splits(); for split in &splits { - self.paint_split_opengl(split, &pane).ok(); + self.paint_split_opengl(split, &pane)?; } } @@ -2342,46 +2375,10 @@ impl TermWindow { if pos.is_active { self.update_text_cursor(&pos.pane); } - if let Err(err) = self.paint_pane_opengl(&pos) { - if let Some(&OutOfTextureSpace { size: Some(size) }) = - err.downcast_ref::() - { - if pass == 0 { - // Let's try clearing out the atlas and trying again - if let Ok(()) = self.render_state.clear_texture_atlas(&self.render_metrics) - { - log::trace!("cleared atlas"); - return self.paint_opengl_pass(frame, pass + 1); - } - } - - log::error!("out of texture space, allocating {}", size); - match self.recreate_texture_atlas(Some(size)) { - Ok(_) => { - // Recursively initiate a new paint - return self.paint_opengl_pass(frame, pass + 1); - } - Err(err) => { - log::error!("failed recreate atlas with size {}: {}", size, err); - // Failed to increase the size. - // This might happen if a lot of images have been displayed in the - // terminal over time and we've hit a texture size limit. - // Let's just try recreating at the current size. - self.recreate_texture_atlas(None) - .expect("OutOfTextureSpace and failed to recreate atlas"); - } - } - } else { - log::error!("paint_pane_opengl failed: {}", err); - } - } + self.paint_pane_opengl(&pos)?; } - self.call_draw(frame).ok(); - log::debug!("paint_pane_opengl elapsed={:?}", start.elapsed()); - metrics::value!("gui.paint.opengl", start.elapsed()); - - self.update_title(); + Ok(()) } fn paint_pane_opengl(&mut self, pos: &PositionedPane) -> anyhow::Result<()> {