From 97420f13d896ef0dc4c956fcc89d5818769ced88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 26 Jun 2019 19:33:39 +0200 Subject: [PATCH] scroll: let the render erase the scrolled up region The grid scroll operation no longer inserts a DAMAGE_ERASE operation, but instead manually clears the region. The render does the corresponding thing. --- grid.c | 44 +++++++++++++++++++------------------------- main.c | 46 ++++++++++++++++++++++++++++++++-------------- 2 files changed, 51 insertions(+), 39 deletions(-) diff --git a/grid.c b/grid.c index f588f6e0..2663952d 100644 --- a/grid.c +++ b/grid.c @@ -164,26 +164,22 @@ grid_damage_scroll(struct grid *grid, enum damage_type damage_type, { damage_adjust_after_scroll(grid, damage_type, region, lines); - if (tll_length(grid->scroll_damage) > 0 && - tll_back(grid->scroll_damage).type == damage_type && - tll_back(grid->scroll_damage).scroll.region.start == region.start && - tll_back(grid->scroll_damage).scroll.region.end == region.end) - { - /* Merge with existing scroll damage */ - + if (tll_length(grid->scroll_damage) > 0) { struct damage *dmg = &tll_back(grid->scroll_damage); - dmg->scroll.lines += lines; - /* If we've scrolled away the entire screen, remove it all together */ - if (dmg->scroll.lines >= region.end - region.start) - tll_pop_back(grid->scroll_damage); - } else { - struct damage dmg = { - .type = damage_type, - .scroll = {.region = region, .lines = lines}, - }; - tll_push_back(grid->scroll_damage, dmg); + if (dmg->type == damage_type && + dmg->scroll.region.start == region.start && + dmg->scroll.region.end == region.end) + { + dmg->scroll.lines += lines; + return; + } } + struct damage dmg = { + .type = damage_type, + .scroll = {.region = region, .lines = lines}, + }; + tll_push_back(grid->scroll_damage, dmg); } void @@ -277,11 +273,10 @@ grid_scroll_partial(struct grid *grid, struct scroll_region region, int rows) &grid->cells[cell_dst], &grid->cells[cell_src], bytes); + memset(&grid->cells[(region.end - rows) * grid->cols], 0, + rows * grid->cols * sizeof(grid->cells[0])); + grid_damage_scroll(grid, DAMAGE_SCROLL, region, rows); - grid_erase( - grid, - (region.end - rows) * grid->cols, - region.end * grid->cols); } void @@ -311,11 +306,10 @@ grid_scroll_reverse_partial(struct grid *grid, &grid->cells[cell_dst], &grid->cells[cell_src], bytes); + memset(&grid->cells[cell_src], 0, + rows * grid->cols * sizeof(grid->cells[0])); + grid_damage_scroll(grid, DAMAGE_SCROLL_REVERSE, region, rows); - grid_erase( - grid, - region.start * grid->cols, - (region.start + rows) * grid->cols); } void diff --git a/main.c b/main.c index 296414b7..781db37b 100644 --- a/main.c +++ b/main.c @@ -27,6 +27,7 @@ #include "grid.h" #define min(x, y) ((x) < (y) ? (x) : (y)) +#define max(x, y) ((x) > (y) ? (x) : (y)) static const uint32_t default_foreground = 0xffffffff; static const uint32_t default_background = 0x000000ff; @@ -269,25 +270,28 @@ grid_render_scroll(struct context *c, struct buffer *buf, dst_y, src_y, height, stride, buf->size); - cairo_surface_flush(buf->cairo_surface); - uint8_t *raw = cairo_image_surface_get_data(buf->cairo_surface); + if (height > 0) { + cairo_surface_flush(buf->cairo_surface); + uint8_t *raw = cairo_image_surface_get_data(buf->cairo_surface); - memmove(raw + dst_y * stride, raw + src_y * stride, height * stride); - cairo_surface_mark_dirty(buf->cairo_surface); + memmove(raw + dst_y * stride, raw + src_y * stride, height * stride); + cairo_surface_mark_dirty(buf->cairo_surface); - wl_surface_damage_buffer(c->wl.surface, 0, dst_y, width, height); + wl_surface_damage_buffer(c->wl.surface, 0, dst_y, width, height); + } -#if 0 const int cols = c->term.grid.cols; + struct damage erase = { .type = DAMAGE_ERASE, .range = { - .start = (dmg->scroll.region.end - dmg->scroll.lines) * cols, - .length = dmg->scroll.lines * cols + .start = max(dmg->scroll.region.end - dmg->scroll.lines, + dmg->scroll.region.start) * cols, + .length = min(dmg->scroll.region.end - dmg->scroll.region.start, + dmg->scroll.lines) * cols, }, }; grid_render_erase(c, buf, &erase); -#endif } static void @@ -308,13 +312,27 @@ grid_render_scroll_reverse(struct context *c, struct buffer *buf, dst_y, src_y, height, stride, buf->size); - cairo_surface_flush(buf->cairo_surface); - uint8_t *raw = cairo_image_surface_get_data(buf->cairo_surface); + if (height > 0) { + cairo_surface_flush(buf->cairo_surface); + uint8_t *raw = cairo_image_surface_get_data(buf->cairo_surface); - memmove(raw + dst_y * stride, raw + src_y * stride, height * stride); - cairo_surface_mark_dirty(buf->cairo_surface); + memmove(raw + dst_y * stride, raw + src_y * stride, height * stride); + cairo_surface_mark_dirty(buf->cairo_surface); - wl_surface_damage_buffer(c->wl.surface, 0, dst_y, width, height); + wl_surface_damage_buffer(c->wl.surface, 0, dst_y, width, height); + } + + const int cols = c->term.grid.cols; + + struct damage erase = { + .type = DAMAGE_ERASE, + .range = { + .start = dmg->scroll.region.start * cols, + .length = min(dmg->scroll.region.end - dmg->scroll.region.start, + dmg->scroll.lines) * cols, + }, + }; + grid_render_erase(c, buf, &erase); } static void