diff --git a/kitty/char_grid.py b/kitty/char_grid.py index 66fa9930a..365273abd 100644 --- a/kitty/char_grid.py +++ b/kitty/char_grid.py @@ -5,7 +5,7 @@ import re import sys from collections import namedtuple -from ctypes import addressof, memmove, sizeof +from ctypes import addressof, sizeof from enum import Enum from .config import build_ansi_color_table, defaults @@ -159,10 +159,11 @@ class CharGrid: def __init__(self, screen, opts): self.vao_id = None self.current_selection = Selection() + self.scroll_changed = False self.last_rendered_selection = None - self.render_buf_is_dirty = True self.render_data = None self.scrolled_by = 0 + self.data_buffer_size = 0 self.screen = screen self.opts = opts self.screen.color_profile.update_ansi_color_table(build_ansi_color_table(opts)) @@ -173,7 +174,6 @@ class CharGrid: self.opts = opts self.default_cursor = self.current_cursor = Cursor(0, 0, opts.cursor_shape, opts.cursor_blink_interval > 0) self.opts = opts - self.main_sprite_map = self.scroll_sprite_map = self.render_buf = None def escape(chars): return ''.join(frozenset(chars)).replace('\\', r'\\').replace(']', r'\]').replace('-', r'\-') @@ -194,12 +194,8 @@ class CharGrid: def resize(self, window_geometry): self.update_position(window_geometry) - rt = (GLuint * (self.screen_geometry.ynum * self.screen_geometry.xnum * DATA_CELL_SIZE)) - self.main_sprite_map = rt() - self.scroll_sprite_map = rt() - self.render_buf = rt() + self.data_buffer_size = sizeof(GLuint) * self.screen_geometry.ynum * self.screen_geometry.xnum * DATA_CELL_SIZE self.selection_buf = (GLfloat * (self.screen_geometry.ynum * self.screen_geometry.xnum))() - self.render_buf_is_dirty = True self.current_selection.clear() def change_colors(self, changes): @@ -228,21 +224,17 @@ class CharGrid: y = max(0, min(self.scrolled_by + amt, self.screen.historybuf.count)) if y != self.scrolled_by: self.scrolled_by = y - self.update_cell_data() + self.scroll_changed = True - def update_cell_data(self, force_full_refresh=False): - cursor_changed, history_line_added_count = self.screen.update_cell_data( - addressof(self.main_sprite_map), force_full_refresh) - if self.scrolled_by: - self.scrolled_by = min(self.scrolled_by + history_line_added_count, self.screen.historybuf.count) - self.screen.set_scroll_cell_data( - addressof(self.main_sprite_map), self.scrolled_by, addressof(self.scroll_sprite_map)) + def update_cell_data(self, cell_program, force_full_refresh=False): + if self.data_buffer_size == 0: + return + with cell_program.mapped_vertex_data(self.vao_id, self.data_buffer_size) as address: + cursor_changed, self.scrolled_by = self.screen.update_cell_data( + address, self.scrolled_by, force_full_refresh) - data = self.scroll_sprite_map if self.scrolled_by else self.main_sprite_map self.current_selection.clear() - memmove(self.render_buf, data, sizeof(type(data))) self.render_data = self.screen_geometry - self.render_buf_is_dirty = True if cursor_changed: c = self.screen.cursor self.current_cursor = Cursor(c.x, c.y, c.shape, c.blink) @@ -363,20 +355,18 @@ class CharGrid: return s.text(self.screen.linebuf, self.screen.historybuf) def prepare_for_render(self, cell_program): - if self.screen.is_dirty(): - self.update_cell_data() - sg = self.render_data if self.vao_id is None: self.vao_id = cell_program.create_sprite_map() + if self.scroll_changed or self.screen.is_dirty(): + self.update_cell_data(cell_program) + self.scroll_changed = False + sg = self.render_data start, end = sel = self.current_selection.limits(self.scrolled_by, self.screen.lines, self.screen.columns) selection_changed = sel != self.last_rendered_selection if selection_changed: self.screen.apply_selection(addressof(self.selection_buf), start[0], start[1], end[0], end[1], len(self.selection_buf)) cell_program.send_vertex_data(self.vao_id, self.selection_buf, bufnum=1) self.last_rendered_selection = sel - if self.render_buf_is_dirty: - cell_program.send_vertex_data(self.vao_id, self.render_buf) - self.render_buf_is_dirty = False return sg def render_cells(self, sg, cell_program, sprites, invert_colors=False): diff --git a/kitty/screen.c b/kitty/screen.c index 4cffdda9f..ca4b6f3b7 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -1193,38 +1193,24 @@ screen_update_cell_data(Screen *self, PyObject *args) { PyObject *dp; unsigned int *data; int force_screen_refresh; - if (!PyArg_ParseTuple(args, "O!p", &PyLong_Type, &dp, &force_screen_refresh)) return NULL; + unsigned int scrolled_by; + unsigned int history_line_added_count = self->change_tracker->history_line_added_count; + if (!PyArg_ParseTuple(args, "O!Ip", &PyLong_Type, &dp, &scrolled_by, &force_screen_refresh)) return NULL; data = PyLong_AsVoidPtr(dp); PyObject *cursor_changed = self->change_tracker->cursor_changed ? Py_True : Py_False; - unsigned int history_line_added_count = self->change_tracker->history_line_added_count; - - if (!tracker_update_cell_data(&(self->modes), self->change_tracker, self->linebuf, data, (bool)force_screen_refresh)) return NULL; - return Py_BuildValue("OI", cursor_changed, history_line_added_count); -} - -static PyObject* -set_scroll_cell_data(Screen *self, PyObject *args) { - PyObject *dp, *sp; - unsigned int *data, *src, scrolled_by; - if (!PyArg_ParseTuple(args, "O!IO", &PyLong_Type, &sp, &scrolled_by, &dp)) return NULL; - data = PyLong_AsVoidPtr(dp); - src = PyLong_AsVoidPtr(sp); - - scrolled_by = MIN(self->historybuf->count, scrolled_by); - + if (scrolled_by) scrolled_by = MIN(scrolled_by + history_line_added_count, self->historybuf->count); + tracker_reset(self->change_tracker); for (index_type y = 0; y < MIN(self->lines, scrolled_by); y++) { historybuf_init_line(self->historybuf, scrolled_by - 1 - y, self->historybuf->line); self->historybuf->line->ynum = y; if (!update_cell_range_data(&(self->modes), self->historybuf->line, 0, self->columns - 1, data)) return NULL; } - if (scrolled_by < self->lines) { - // Less than a full screen has been scrolled, copy some lines from the screen buffer to the scroll buffer - unsigned int line_size = DATA_CELL_SIZE * self->columns; - index_type num_to_copy = self->lines - scrolled_by; - index_type offset = line_size * scrolled_by; - memcpy(data + offset, src, line_size * num_to_copy * sizeof(unsigned int)); + for (index_type y = scrolled_by; y < self->lines; y++) { + linebuf_init_line(self->linebuf, y - scrolled_by); + self->linebuf->line->ynum = y; + if (!update_cell_range_data(&(self->modes), self->linebuf->line, 0, self->columns - 1, data)) return NULL; } - Py_RETURN_NONE; + return Py_BuildValue("OI", cursor_changed, scrolled_by); } static PyObject* @@ -1331,7 +1317,6 @@ static PyMethodDef methods[] = { MND(mark_as_dirty, METH_NOARGS) MND(resize, METH_VARARGS) MND(set_margins, METH_VARARGS) - MND(set_scroll_cell_data, METH_VARARGS) MND(apply_selection, METH_VARARGS) MND(toggle_alt_screen, METH_NOARGS) MND(reset_callbacks, METH_NOARGS)