wip: use a sliding window instead of memmove() to scroll

Instead of memmoving a large amount of data on every scroll, use a
sliding window. That is, each time we scroll, we offset origin.
This commit is contained in:
Daniel Eklöf 2019-07-01 12:23:38 +02:00
parent 9e3b8ab3ff
commit d70956da08
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
7 changed files with 140 additions and 108 deletions

View file

@ -6,6 +6,7 @@
#define LOG_MODULE "terminal"
#define LOG_ENABLE_DBG 1
#include "log.h"
#include "grid.h"
#define min(x, y) ((x) < (y) ? (x) : (y))
#define max(x, y) ((x) > (y) ? (x) : (y))
@ -37,10 +38,6 @@ damage_merge_range(struct terminal *term, const struct damage *dmg)
old->range.start = new_start;
old->range.length = new_end - new_start;
assert(old->range.start >= 0);
assert(old->range.start < term->rows * term->cols);
assert(old->range.length >= 0);
assert(old->range.start + old->range.length <= term->rows * term->cols);
return true;
}
@ -53,14 +50,8 @@ term_damage_update_or_erase(struct terminal *term, enum damage_type damage_type,
{
struct damage dmg = {
.type = damage_type,
.range = {.start = start, .length = length},
.range = {.start = term->grid->offset + start, .length = length},
};
assert(dmg.range.start >= 0);
assert(dmg.range.start < term->rows * term->cols);
assert(dmg.range.length >= 0);
assert(dmg.range.start + dmg.range.length <= term->rows * term->cols);
if (damage_merge_range(term, &dmg))
return;
@ -70,12 +61,14 @@ term_damage_update_or_erase(struct terminal *term, enum damage_type damage_type,
void
term_damage_update(struct terminal *term, int start, int length)
{
assert(start + length <= term->rows * term->cols);
term_damage_update_or_erase(term, DAMAGE_UPDATE, start, length);
}
void
term_damage_erase(struct terminal *term, int start, int length)
{
assert(start + length <= term->rows * term->cols);
term_damage_update_or_erase(term, DAMAGE_ERASE, start, length);
}
@ -87,82 +80,30 @@ term_damage_all(struct terminal *term)
term_damage_update(term, 0, term->rows * term->cols);
}
#if 0
static void
damage_adjust_after_scroll(struct terminal *term, enum damage_type damage_type,
struct scroll_region region, int lines)
{
const int adjustment
= lines * term->cols * (damage_type == DAMAGE_SCROLL_REVERSE ? -1 : 1);
const int scroll_start = region.start * term->cols;
const int scroll_end = region.end * term->cols;
tll_foreach(term->grid->damage, it) {
int start = it->item.range.start;
int length = it->item.range.length;
int end = start + length;
if (start < scroll_start && end > scroll_start) {
/* Start outside, end either inside or on the other side */
struct damage outside = {
.type = it->item.type,
.range = {.start = start, .length = scroll_start - start},
};
tll_push_back(term->grid->damage, outside);
start = scroll_start;
length = end - start;
}
if (start < scroll_end && end > scroll_end) {
/* End outside, start either inside or on the other side */
struct damage outside = {
.type = it->item.type,
.range = {.start = scroll_end, .length = length - scroll_end},
};
tll_push_back(term->grid->damage, outside);
end = scroll_end;
length = end - start;
}
if (start >= scroll_start && end <= scroll_end) {
/* Completely inside scroll region */
start -= adjustment;
it->item.range.start = start;
if (start < scroll_start) {
/* Scrolled up outside scroll region */
int new_length = length - (scroll_start - start);
assert(new_length < length);
if (new_length <= 0)
tll_remove(term->grid->damage, it);
else {
it->item.range.start = scroll_start;
it->item.range.length = new_length;
}
}
if (start + length > scroll_end) {
/* Scrolled down outside scroll region */
if (start >= scroll_end)
tll_remove(term->grid->damage, it);
else {
it->item.range.start = start;
it->item.range.length = scroll_end - start;
}
if (it->item.range.start < term->grid->offset) {
int end = it->item.range.start + it->item.range.length;
if (end >= term->grid->offset) {
it->item.range.start = term->grid->offset;
it->item.range.length = end - it->item.range.start;
} else {
tll_remove(term->grid->damage, it);
}
}
}
}
#endif
void
term_damage_scroll(struct terminal *term, enum damage_type damage_type,
struct scroll_region region, int lines)
{
damage_adjust_after_scroll(term, damage_type, region, lines);
//damage_adjust_after_scroll(term, damage_type, region, lines);
if (tll_length(term->grid->scroll_damage) > 0) {
struct damage *dmg = &tll_back(term->grid->scroll_damage);
@ -185,8 +126,11 @@ term_damage_scroll(struct terminal *term, enum damage_type damage_type,
void
term_erase(struct terminal *term, int start, int end)
{
LOG_DBG("erase: %d-%d", start, end);
assert(end >= start);
memset(&term->grid->cells[start], 0, (end - start) * sizeof(term->grid->cells[0]));
assert(end <= term->rows * term->cols);
grid_memset(term->grid, start, 0, end - start);
term_damage_erase(term, start, end - start);
}
@ -199,13 +143,10 @@ term_cursor_linear(const struct terminal *term, int row, int col)
void
term_cursor_to(struct terminal *term, int row, int col)
{
assert(row >= 0);
assert(row < term->rows);
assert(col >= 0);
assert(col < term->cols);
int new_linear = row * term->cols + col;
assert(new_linear >= 0);
assert(new_linear < term->rows * term->cols);
term_damage_update(term, term->cursor.linear, 1);
@ -248,11 +189,13 @@ term_cursor_down(struct terminal *term, int count)
void
term_scroll_partial(struct terminal *term, struct scroll_region region, int rows)
{
LOG_DBG("scroll: %d rows", rows);
if (rows >= region.end - region.start) {
assert(false && "untested");
return;
}
#if 0
int cell_dst = (region.start + 0) * term->cols;
int cell_src = (region.start + rows) * term->cols;
int cell_count = (region.end - region.start - rows) * term->cols;
@ -260,7 +203,7 @@ term_scroll_partial(struct terminal *term, struct scroll_region region, int rows
LOG_DBG("moving %d lines from row %d to row %d", cell_count / term->cols,
cell_src / term->cols, cell_dst / term->cols);
const size_t bytes = cell_count * sizeof(term->grid->cells[0]);
const int bytes = cell_count * sizeof(term->grid->cells[0]);
memmove(
&term->grid->cells[cell_dst], &term->grid->cells[cell_src],
bytes);
@ -269,6 +212,15 @@ term_scroll_partial(struct terminal *term, struct scroll_region region, int rows
rows * term->cols * sizeof(term->grid->cells[0]));
term_damage_scroll(term, DAMAGE_SCROLL, region, rows);
#else
/* TODO */
assert(region.start == 0 && region.end == term->rows);
assert(rows < term->rows);
term->grid->offset += rows * term->cols;
grid_memset(term->grid, (region.end - rows) * term->cols, 0, rows * term->cols);
term_damage_scroll(term, DAMAGE_SCROLL, region, rows);
#endif
}
void
@ -286,6 +238,7 @@ term_scroll_reverse_partial(struct terminal *term,
return;
}
#if 0
int cell_dst = (region.start + rows) * term->cols;
int cell_src = (region.start + 0) * term->cols;
int cell_count = (region.end - region.start - rows) * term->cols;
@ -293,7 +246,7 @@ term_scroll_reverse_partial(struct terminal *term,
LOG_DBG("moving %d lines from row %d to row %d", cell_count / term->cols,
cell_src / term->cols, cell_dst / term->cols);
const size_t bytes = cell_count * sizeof(term->grid->cells[0]);
const int bytes = cell_count * sizeof(term->grid->cells[0]);
memmove(
&term->grid->cells[cell_dst], &term->grid->cells[cell_src],
bytes);
@ -302,6 +255,15 @@ term_scroll_reverse_partial(struct terminal *term,
rows * term->cols * sizeof(term->grid->cells[0]));
term_damage_scroll(term, DAMAGE_SCROLL_REVERSE, region, rows);
#else
/* TODO */
assert(false);
assert(region.start == 0 && region.end == 0);
assert(rows < term->rows);
term->grid->offset -= rows * term->cols;
term_damage_scroll(term, DAMAGE_SCROLL_REVERSE, region, rows);
#endif
}
void