mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-03-06 01:40:22 -05:00
shm: scroll: move top/bottom region handling from renderer into shm
This allows us to restore the regions without copying the contents to temporary memory.
This commit is contained in:
parent
00129b1935
commit
0de3701984
3 changed files with 57 additions and 59 deletions
63
render.c
63
render.c
|
|
@ -551,7 +551,6 @@ grid_render_scroll(struct terminal *term, struct buffer *buf,
|
||||||
gettimeofday(&start_time, NULL);
|
gettimeofday(&start_time, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint8_t *raw = buf->mmapped;
|
|
||||||
int dst_y = term->margins.top + (dmg->scroll.region.start + 0) * term->cell_height;
|
int dst_y = term->margins.top + (dmg->scroll.region.start + 0) * term->cell_height;
|
||||||
int src_y = term->margins.top + (dmg->scroll.region.start + dmg->scroll.lines) * term->cell_height;
|
int src_y = term->margins.top + (dmg->scroll.region.start + dmg->scroll.lines) * term->cell_height;
|
||||||
|
|
||||||
|
|
@ -563,12 +562,13 @@ grid_render_scroll(struct terminal *term, struct buffer *buf,
|
||||||
* memmove, while scrolling a *small* number of lines is faster
|
* memmove, while scrolling a *small* number of lines is faster
|
||||||
* with SHM scrolling.
|
* with SHM scrolling.
|
||||||
*
|
*
|
||||||
* However, since we need to restore the bottom scrolling region
|
* However, since we need to restore the scrolling regions when
|
||||||
* when SHM scrolling, we also need to take this into account.
|
* SHM scrolling, we also need to take this into account.
|
||||||
*
|
*
|
||||||
* Finally, restoring the window margins is a *huge* performance
|
* Finally, we also have to restore the window margins, and this
|
||||||
* hit when scrolling a large number of lines (in addition to the
|
* is a *huge* performance hit when scrolling a large number of
|
||||||
* sloweness of SHM scrolling as method).
|
* lines (in addition to the sloweness of SHM scrolling as
|
||||||
|
* method).
|
||||||
*
|
*
|
||||||
* So, we need to figure out when to SHM scroll, and when to
|
* So, we need to figure out when to SHM scroll, and when to
|
||||||
* memmove.
|
* memmove.
|
||||||
|
|
@ -597,19 +597,11 @@ grid_render_scroll(struct terminal *term, struct buffer *buf,
|
||||||
//try_shm_scroll = false;
|
//try_shm_scroll = false;
|
||||||
//try_shm_scroll = true;
|
//try_shm_scroll = true;
|
||||||
|
|
||||||
/* TODO: this could easily use up all stack */
|
|
||||||
uint8_t top_region[dmg->scroll.region.start * term->cell_height * buf->stride];
|
|
||||||
|
|
||||||
if (try_shm_scroll) {
|
if (try_shm_scroll) {
|
||||||
if (dmg->scroll.region.start > 0) {
|
|
||||||
/* Store a copy of the top region - we need to restore it after scrolling */
|
|
||||||
memcpy(top_region,
|
|
||||||
(uint8_t *)buf->mmapped + term->margins.top * buf->stride,
|
|
||||||
sizeof(top_region));
|
|
||||||
}
|
|
||||||
|
|
||||||
did_shm_scroll = shm_scroll(
|
did_shm_scroll = shm_scroll(
|
||||||
term->wl->shm, buf, dmg->scroll.lines * term->cell_height);
|
term->wl->shm, buf, dmg->scroll.lines * term->cell_height,
|
||||||
|
term->margins.top, dmg->scroll.region.start * term->cell_height,
|
||||||
|
term->margins.bottom, (term->rows - dmg->scroll.region.end) * term->cell_height);
|
||||||
|
|
||||||
if (!did_shm_scroll)
|
if (!did_shm_scroll)
|
||||||
LOG_DBG("fast scroll failed");
|
LOG_DBG("fast scroll failed");
|
||||||
|
|
@ -620,47 +612,14 @@ grid_render_scroll(struct terminal *term, struct buffer *buf,
|
||||||
dmb->scroll.region.start, scroll_region_lines, term->rows);
|
dmb->scroll.region.start, scroll_region_lines, term->rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* When SHM scrolling succeeded, the scrolled in area is made up
|
|
||||||
* of newly allocated, zero-initialized memory. Thus we'll need to
|
|
||||||
* both copy the bottom scrolling region, and re-render the window
|
|
||||||
* margins.
|
|
||||||
*
|
|
||||||
* This is different from when we scroll with a simple memmove,
|
|
||||||
* since in that case, the scrolling region and margins are
|
|
||||||
* *copied*, and thus the original region+margin remains in place.
|
|
||||||
*/
|
|
||||||
if (did_shm_scroll) {
|
if (did_shm_scroll) {
|
||||||
|
|
||||||
/* Mmap changed - update buffer pointer */
|
|
||||||
raw = buf->mmapped;
|
|
||||||
|
|
||||||
/* Restore top scrolling region */
|
|
||||||
memcpy(raw + term->margins.top * buf->stride, top_region, sizeof(top_region));
|
|
||||||
|
|
||||||
/* Restore bottom scrolling region */
|
|
||||||
if (dmg->scroll.region.end < term->rows) {
|
|
||||||
int src = dmg->scroll.region.end - dmg->scroll.lines;
|
|
||||||
int dst = dmg->scroll.region.end;
|
|
||||||
size_t amount = term->rows - dmg->scroll.region.end;
|
|
||||||
|
|
||||||
LOG_DBG("memmoving %zu lines of scroll region", amount);
|
|
||||||
assert(src >= 0);
|
|
||||||
|
|
||||||
memmove(
|
|
||||||
raw + (term->margins.top + dst * term->cell_height) * buf->stride,
|
|
||||||
raw + (term->margins.top + src * term->cell_height) * buf->stride,
|
|
||||||
amount * term->cell_height * buf->stride);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Restore margins */
|
/* Restore margins */
|
||||||
render_margin(
|
render_margin(
|
||||||
term, buf, dmg->scroll.region.end - dmg->scroll.lines, term->rows,
|
term, buf, dmg->scroll.region.end - dmg->scroll.lines, term->rows,
|
||||||
true, true);
|
true, true);
|
||||||
}
|
} else {
|
||||||
|
/* Fallback for when we either cannot do SHM scrolling, or it failed */
|
||||||
/* Fallback for when we either cannot do SHM scrolling, or it failed */
|
|
||||||
if (!did_shm_scroll) {
|
|
||||||
uint8_t *raw = buf->mmapped;
|
uint8_t *raw = buf->mmapped;
|
||||||
memmove(raw + dst_y * buf->stride,
|
memmove(raw + dst_y * buf->stride,
|
||||||
raw + src_y * buf->stride,
|
raw + src_y * buf->stride,
|
||||||
|
|
|
||||||
49
shm.c
49
shm.c
|
|
@ -287,7 +287,9 @@ shm_can_scroll(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
shm_scroll(struct wl_shm *shm, struct buffer *buf, int rows)
|
shm_scroll(struct wl_shm *shm, struct buffer *buf, int rows,
|
||||||
|
int top_margin, int top_keep_rows,
|
||||||
|
int bottom_margin, int bottom_keep_rows)
|
||||||
{
|
{
|
||||||
assert(can_punch_hole);
|
assert(can_punch_hole);
|
||||||
assert(buf->busy);
|
assert(buf->busy);
|
||||||
|
|
@ -323,9 +325,25 @@ shm_scroll(struct wl_shm *shm, struct buffer *buf, int rows)
|
||||||
|
|
||||||
struct timeval tot;
|
struct timeval tot;
|
||||||
timersub(&time1, &time0, &tot);
|
timersub(&time1, &time0, &tot);
|
||||||
LOG_INFO("fallocate: %lds %ldus", tot.tv_sec, tot.tv_usec);
|
LOG_INFO("ftruncate: %lds %ldus", tot.tv_sec, tot.tv_usec);
|
||||||
|
|
||||||
|
struct timeval time2 = time1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (top_keep_rows > 0) {
|
||||||
|
/* Copy current 'top' region to its new location */
|
||||||
|
memmove(
|
||||||
|
(uint8_t *)buf->mmapped + (top_margin + rows) * buf->stride,
|
||||||
|
(uint8_t *)buf->mmapped + (top_margin + 0) * buf->stride,
|
||||||
|
top_keep_rows * buf->stride);
|
||||||
|
|
||||||
|
#if TIME_SCROLL
|
||||||
|
gettimeofday(&time2, NULL);
|
||||||
|
timersub(&time2, &time1, &tot);
|
||||||
|
LOG_INFO("memmove (top region): %lds %ldus", tot.tv_sec, tot.tv_usec);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* Destroy old objects (they point to the old offset) */
|
/* Destroy old objects (they point to the old offset) */
|
||||||
pixman_image_unref(buf->pix);
|
pixman_image_unref(buf->pix);
|
||||||
wl_buffer_destroy(buf->wl_buf);
|
wl_buffer_destroy(buf->wl_buf);
|
||||||
|
|
@ -341,13 +359,32 @@ shm_scroll(struct wl_shm *shm, struct buffer *buf, int rows)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TIME_SCROLL
|
#if TIME_SCROLL
|
||||||
struct timeval time2;
|
struct timeval time3;
|
||||||
gettimeofday(&time2, NULL);
|
gettimeofday(&time3, NULL);
|
||||||
timersub(&time2, &time1, &tot);
|
timersub(&time3, &time2, &tot);
|
||||||
LOG_INFO("PUNCH HOLE: %lds %ldus", tot.tv_sec, tot.tv_usec);
|
LOG_INFO("PUNCH HOLE: %lds %ldus", tot.tv_sec, tot.tv_usec);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return instantiate_offset(shm, buf, new_offset);
|
|
||||||
|
bool ret = instantiate_offset(shm, buf, new_offset);
|
||||||
|
|
||||||
|
if (ret && bottom_keep_rows > 0) {
|
||||||
|
/* Copy 'bottom' region to its new location */
|
||||||
|
memmove(
|
||||||
|
(uint8_t *)buf->mmapped + buf->size - (bottom_margin + bottom_keep_rows) * buf->stride,
|
||||||
|
(uint8_t *)buf->mmapped + buf->size - (bottom_margin + rows + bottom_keep_rows) * buf->stride,
|
||||||
|
bottom_keep_rows * buf->stride);
|
||||||
|
|
||||||
|
#if TIME_SCROLL
|
||||||
|
struct timeval time4;
|
||||||
|
gettimeofday(&time4, NULL);
|
||||||
|
|
||||||
|
timersub(&time4, &time3, &tot);
|
||||||
|
LOG_INFO("memmove (bottom region): %lds %ldus", tot.tv_sec, tot.tv_usec);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
4
shm.h
4
shm.h
|
|
@ -33,7 +33,9 @@ struct buffer *shm_get_buffer(
|
||||||
void shm_fini(void);
|
void shm_fini(void);
|
||||||
|
|
||||||
bool shm_can_scroll(void);
|
bool shm_can_scroll(void);
|
||||||
bool shm_scroll(struct wl_shm *shm, struct buffer *buf, int rows);
|
bool shm_scroll(struct wl_shm *shm, struct buffer *buf, int rows,
|
||||||
|
int top_margin, int top_keep_rows,
|
||||||
|
int bottom_margin, int bottom_keep_rows);
|
||||||
|
|
||||||
void shm_purge(struct wl_shm *shm, unsigned long cookie);
|
void shm_purge(struct wl_shm *shm, unsigned long cookie);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue