1
1
mirror of https://github.com/wez/wezterm.git synced 2024-09-20 19:27:22 +03:00

software: handle OutOfTextureSpace condition

This commit is contained in:
Wez Furlong 2019-09-29 12:42:51 -07:00
parent 91e6bb4a5a
commit 569408de66
3 changed files with 37 additions and 10 deletions

View File

@ -144,6 +144,7 @@ pub trait TerminalWindow {
None => return Ok(()), None => return Ok(()),
}; };
let start = std::time::Instant::now();
let mut target = self.frame(); let mut target = self.frame();
let res = { let res = {
let renderer = self.renderer(); let renderer = self.renderer();
@ -156,6 +157,7 @@ pub trait TerminalWindow {
target target
.finish() .finish()
.expect("target.finish failed and we don't know how to recover"); .expect("target.finish failed and we don't know how to recover");
log::debug!("paint elapsed={:?}", start.elapsed());
// The only error we want to catch is texture space related; // The only error we want to catch is texture space related;
// when that happens we need to blow our glyph cache and // when that happens we need to blow our glyph cache and

View File

@ -9,7 +9,7 @@ use crate::mux::renderable::Renderable;
use crate::mux::tab::{Tab, TabId}; use crate::mux::tab::{Tab, TabId};
use crate::mux::window::WindowId as MuxWindowId; use crate::mux::window::WindowId as MuxWindowId;
use crate::mux::Mux; use crate::mux::Mux;
use ::window::bitmaps::atlas::{Atlas, Sprite, SpriteSlice}; use ::window::bitmaps::atlas::{Atlas, OutOfTextureSpace, Sprite, SpriteSlice};
use ::window::bitmaps::{Image, ImageTexture}; use ::window::bitmaps::{Image, ImageTexture};
use ::window::*; use ::window::*;
use failure::Fallible; use failure::Fallible;
@ -245,7 +245,22 @@ impl WindowCallbacks for TermWindow {
return; return;
} }
}; };
self.paint_tab(&tab, ctx); let start = std::time::Instant::now();
if let Err(err) = self.paint_tab(&tab, ctx) {
if let Some(&OutOfTextureSpace { size }) = err.downcast_ref::<OutOfTextureSpace>() {
log::error!("out of texture space, allocating {}", size);
match self.recreate_texture_atlas(size) {
Ok(_) => {
tab.renderer().make_all_lines_dirty();
// Recursively initiate a new paint
return self.paint(ctx);
}
Err(err) => log::error!("failed recreate atlas: {}", err),
};
}
log::error!("paint failed: {}", err);
}
log::debug!("paint_tab elapsed={:?}", start.elapsed());
self.update_title(); self.update_title();
} }
} }
@ -331,6 +346,14 @@ impl TermWindow {
Ok(()) Ok(())
} }
fn recreate_texture_atlas(&mut self, size: usize) -> Fallible<()> {
let surface = Rc::new(ImageTexture::new(size, size));
let atlas = RefCell::new(Atlas::new(&surface).expect("failed to create new texture atlas"));
self.glyph_cache.borrow_mut().clear();
self.atlas = atlas;
Ok(())
}
fn update_title(&mut self) { fn update_title(&mut self) {
let mux = Mux::get().unwrap(); let mux = Mux::get().unwrap();
let window = match mux.get_window(self.mux_window_id) { let window = match mux.get_window(self.mux_window_id) {
@ -513,9 +536,9 @@ impl TermWindow {
metrics.cell_width.ceil() as usize, metrics.cell_width.ceil() as usize,
); );
let surface = Rc::new(ImageTexture::new(4096, 4096)); let atlas_size = self.atlas.borrow().size();
let atlas = self.recreate_texture_atlas(atlas_size)
RefCell::new(Atlas::new(&surface).expect("failed to create new texture atlas")); .expect("failed to recreate atlas");
let descender_row = (cell_height as f64 + metrics.descender) as isize; let descender_row = (cell_height as f64 + metrics.descender) as isize;
let descender_plus_one = (1 + descender_row).min(cell_height as isize - 1); let descender_plus_one = (1 + descender_row).min(cell_height as isize - 1);
@ -527,8 +550,6 @@ impl TermWindow {
self.descender_plus_one = descender_plus_one; self.descender_plus_one = descender_plus_one;
self.descender_plus_two = descender_plus_two; self.descender_plus_two = descender_plus_two;
self.strike_row = strike_row; self.strike_row = strike_row;
self.glyph_cache.borrow_mut().clear();
self.atlas = atlas;
self.cell_size = Size::new(cell_width as isize, cell_height as isize); self.cell_size = Size::new(cell_width as isize, cell_height as isize);
} }
@ -570,7 +591,7 @@ impl TermWindow {
self.activate_tab_relative(0).ok(); self.activate_tab_relative(0).ok();
} }
fn paint_tab(&mut self, tab: &Rc<dyn Tab>, ctx: &mut dyn PaintContext) { fn paint_tab(&mut self, tab: &Rc<dyn Tab>, ctx: &mut dyn PaintContext) -> Fallible<()> {
let palette = tab.palette(); let palette = tab.palette();
let mut term = tab.renderer(); let mut term = tab.renderer();
@ -580,8 +601,7 @@ impl TermWindow {
let dirty_lines = term.get_dirty_lines(); let dirty_lines = term.get_dirty_lines();
for (line_idx, line, selrange) in dirty_lines { for (line_idx, line, selrange) in dirty_lines {
self.render_screen_line(ctx, line_idx, &line, selrange, &cursor, &*term, &palette) self.render_screen_line(ctx, line_idx, &line, selrange, &cursor, &*term, &palette)?;
.ok();
} }
} }
@ -600,6 +620,7 @@ impl TermWindow {
), ),
rgbcolor_to_window_color(palette.background), rgbcolor_to_window_color(palette.background),
); );
Ok(())
} }
fn render_screen_line( fn render_screen_line(

View File

@ -109,6 +109,10 @@ where
coords: rect, coords: rect,
}) })
} }
pub fn size(&self) -> usize {
self.side
}
} }
pub struct Sprite<T> pub struct Sprite<T>