Optimize implementation of clear screen escape code

This commit is contained in:
Kovid Goyal 2024-01-18 12:30:30 +05:30
parent b48b70aedf
commit 89c431a624
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
5 changed files with 27 additions and 10 deletions

View file

@ -372,6 +372,8 @@ cursor_to_attrs(const Cursor *c, const uint16_t width) {
return ans;
}
#define cursor_as_gpu_cell(cursor) {.attrs=cursor_to_attrs(cursor, 0), .fg=(cursor->fg & COL_MASK), .bg=(cursor->bg & COL_MASK), .decoration_fg=cursor->decoration_fg & COL_MASK}
static inline void
attrs_to_cursor(const CellAttrs attrs, Cursor *c) {
c->decoration = attrs.decoration; c->bold = attrs.bold; c->italic = attrs.italic;

View file

@ -146,6 +146,22 @@ linebuf_init_line(LineBuf *self, index_type idx) {
init_line(self, self->line, self->line_map[idx]);
}
void
linebuf_clear_lines(LineBuf *self, const Cursor *cursor, index_type start, index_type end) {
GPUCell *first_gpu_line = gpu_lineptr(self, start);
GPUCell gc = cursor_as_gpu_cell(cursor);
for (index_type i = 0; i < self->xnum; i++) memcpy(first_gpu_line + i, &gc, sizeof(gc));
const size_t cpu_stride = sizeof(self->cpu_cell_buf[0]) * self->xnum;
memset(cpu_lineptr(self, start), 0, cpu_stride);
const size_t gpu_stride = sizeof(self->gpu_cell_buf[0]) * self->xnum;
linebuf_clear_attrs_and_dirty(self, start);
for (index_type i = start + 1; i < end; i++) {
memset(cpu_lineptr(self, i), 0, cpu_stride);
memcpy(gpu_lineptr(self, i), first_gpu_line, gpu_stride);
linebuf_clear_attrs_and_dirty(self, i);
}
}
static PyObject*
line(LineBuf *self, PyObject *y) {
#define line_doc "Return the specified line as a Line object. Note the Line Object is a live view into the underlying buffer. And only a single line object can be used at a time."

View file

@ -539,8 +539,8 @@ clear_text(Line* self, PyObject *args) {
}
void
line_apply_cursor(Line *self, Cursor *cursor, unsigned int at, unsigned int num, bool clear_char) {
GPUCell gc = {.attrs=cursor_to_attrs(cursor, 0), .fg=(cursor->fg & COL_MASK), .bg=(cursor->bg & COL_MASK), .decoration_fg=cursor->decoration_fg & COL_MASK};
line_apply_cursor(Line *self, const Cursor *cursor, unsigned int at, unsigned int num, bool clear_char) {
GPUCell gc = cursor_as_gpu_cell(cursor);
if (clear_char) {
for (index_type i = at; i < self->xnum && i < at + num; i++) {
memset(self->cpu_cells + i, 0, sizeof(self->cpu_cells[0]));

View file

@ -83,7 +83,7 @@ line_is_empty(const Line *line) {
typedef Line*(get_line_func)(void *, int);
void line_clear_text(Line *self, unsigned int at, unsigned int num, char_type ch);
void line_apply_cursor(Line *self, Cursor *cursor, unsigned int at, unsigned int num, bool clear_char);
void line_apply_cursor(Line *self, const Cursor *cursor, unsigned int at, unsigned int num, bool clear_char);
char_type line_get_char(Line *self, index_type at);
void line_set_char(Line *, unsigned int , uint32_t , unsigned int , Cursor *, hyperlink_id_type);
void line_right_shift(Line *, unsigned int , unsigned int );
@ -103,6 +103,7 @@ PyObject* line_as_unicode(Line *, bool);
void linebuf_init_line(LineBuf *, index_type);
void linebuf_init_cells(LineBuf *lb, index_type ynum, CPUCell **c, GPUCell **g);
void linebuf_clear(LineBuf *, char_type ch);
void linebuf_clear_lines(LineBuf *self, const Cursor *cursor, index_type start, index_type end);
void linebuf_index(LineBuf* self, index_type top, index_type bottom);
void linebuf_reverse_index(LineBuf *self, index_type top, index_type bottom);
void linebuf_clear_line(LineBuf *self, index_type y, bool clear_attrs);

View file

@ -1866,16 +1866,14 @@ screen_erase_in_display(Screen *self, unsigned int how, bool private) {
}
if (b > a) {
if (how != 3) screen_dirty_line_graphics(self, a, b, self->linebuf == self->main_linebuf);
for (unsigned int i=a; i < b; i++) {
linebuf_init_line(self->linebuf, i);
if (private) {
if (private) {
for (unsigned int i=a; i < b; i++) {
linebuf_init_line(self->linebuf, i);
line_clear_text(self->linebuf->line, 0, self->columns, BLANK_CHAR);
linebuf_set_last_char_as_continuation(self->linebuf, i, false);
} else {
line_apply_cursor(self->linebuf->line, self->cursor, 0, self->columns, true);
linebuf_clear_attrs_and_dirty(self->linebuf, i);
}
linebuf_clear_attrs_and_dirty(self->linebuf, i);
}
} else linebuf_clear_lines(self->linebuf, self->cursor, a, b);
self->is_dirty = true;
clear_selection(&self->selections);
}