diff --git a/kitty/char_grid.py b/kitty/char_grid.py index 87b6c67be..2ba653457 100644 --- a/kitty/char_grid.py +++ b/kitty/char_grid.py @@ -213,6 +213,7 @@ class CharGrid: def __init__(self, screen, opts): self.buffer_lock = Lock() + self.buffer_id = None self.current_selection = Selection() self.last_rendered_selection = self.current_selection.limits(0, screen.lines, screen.columns) self.render_buf_is_dirty = True @@ -409,6 +410,8 @@ class CharGrid: sg = self.render_data if sg is None: return + if self.buffer_id is None: + self.buffer_id = sprites.add_sprite_map() buf = self.render_buf start, end = sel = self.current_selection.limits(self.scrolled_by, self.screen.lines, self.screen.columns) if start != end: @@ -417,12 +420,13 @@ class CharGrid: memmove(buf, self.render_buf, sizeof(type(buf))) self.screen.apply_selection(addressof(buf), start[0], start[1], end[0], end[1], self.selection_foreground, self.selection_background) if self.render_buf_is_dirty or self.last_rendered_selection != sel: - sprites.set_sprite_map(buf) + sprites.set_sprite_map(self.buffer_id, buf) self.render_buf_is_dirty = False self.last_rendered_selection = sel return sg def render_cells(self, sg, cell_program, sprites): + sprites.bind_sprite_map(self.buffer_id) ul = cell_program.uniform_location glUniform2ui(ul('dimensions'), sg.xnum, sg.ynum) glUniform4f(ul('steps'), sg.xstart, sg.ystart, sg.dx, sg.dy) diff --git a/kitty/shaders.py b/kitty/shaders.py index ae7861386..d27355199 100644 --- a/kitty/shaders.py +++ b/kitty/shaders.py @@ -46,7 +46,7 @@ class Sprites: self.first_cell_cache = {} self.second_cell_cache = {} self.x = self.y = self.z = 0 - self.texture_id = self.buffer_id = self.buffer_texture_id = None + self.texture_id = self.buffer_texture_id = None self.last_num_of_layers = 1 self.last_ynum = -1 self.texture_unit = GL_TEXTURE0 @@ -135,18 +135,25 @@ class Sprites: self.texture_id = None if self.buffer_texture_id is not None: glDeleteTexture(self.buffer_texture_id) - if self.buffer_id is not None: - glDeleteBuffer(self.buffer_id) def ensure_state(self): if self.texture_id is None: self.realloc_texture() - self.buffer_id = glGenBuffers(1) self.buffer_texture_id = glGenTextures(1) self.buffer_texture_unit = GL_TEXTURE1 - def set_sprite_map(self, data, usage=GL_STREAM_DRAW): - glNamedBufferData(self.buffer_id, sizeof(data), addressof(data), usage) + def add_sprite_map(self): + return glGenBuffers(1) + + def set_sprite_map(self, buf_id, data, usage=GL_STREAM_DRAW): + glNamedBufferData(buf_id, sizeof(data), addressof(data), usage) + + def bind_sprite_map(self, buf_id): + glBindBuffer(GL_TEXTURE_BUFFER, buf_id) + glTexBuffer(GL_TEXTURE_BUFFER, GL_RGB32UI, buf_id) + + def destroy_sprite_map(self, buf_id): + glDeleteBuffer(buf_id) def __enter__(self): self.ensure_state() @@ -155,8 +162,6 @@ class Sprites: glActiveTexture(self.buffer_texture_unit) glBindTexture(GL_TEXTURE_BUFFER, self.buffer_texture_id) - glBindBuffer(GL_TEXTURE_BUFFER, self.buffer_id) - glTexBuffer(GL_TEXTURE_BUFFER, GL_RGB32UI, self.buffer_id) def __exit__(self, *a): glBindTexture(GL_TEXTURE_2D_ARRAY, 0) diff --git a/kitty/tabs.py b/kitty/tabs.py index f262ed23a..27631faea 100644 --- a/kitty/tabs.py +++ b/kitty/tabs.py @@ -266,7 +266,7 @@ class TabManager(Thread): glfw_post_empty_event() def close_window(self, window=None): - ' Can be called in either thread, will first kill the child (with SIGHUP), then remove the window from the gui ' + ' Can be called in either thread, will first kill the child, then remove the window from the gui ' if window is None: window = self.active_window if current_thread() is main_thread: @@ -276,6 +276,18 @@ class TabManager(Thread): window.destroy() self.queue_ui_action(self.gui_close_window, window) + def close_tab(self, tab=None): + ' Can be called in either thread, will first kill all children, then remove the tab from the gui ' + if tab is None: + tab = self.active_tab + if current_thread() is main_thread: + self.queue_action(self.close_tab, tab) + else: + for window in tab: + self.remove_child_fd(window.child_fd) + window.destroy() + self.queue_ui_action(self.gui_close_window, window) + def run(self): if self.args.profile: import cProfile @@ -478,6 +490,9 @@ class TabManager(Thread): active.char_grid.render_cursor(rd, self.cursor_program) def gui_close_window(self, window): + if window.char_grid.buffer_id is not None: + self.sprites.destroy_sprite_map(window.char_grid.buffer_id) + window.char_grid.buffer_id = None for tab in self.tabs: if window in tab: break