shm: track busy buffers’ age, and add compile-time option to force double buffering

By default, age all matching buffers that are busy (i.e. in use by the
compositor).

This allows us to detect whether we can apply the current frame’s
damage directly, or if we need to prepare the buffer first (e.g. copy
old buffer, or re-apply last frame’s damage etc).
This commit is contained in:
Daniel Eklöf 2021-05-07 18:18:35 +02:00
parent 1501d36470
commit c8b342ae51
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
3 changed files with 34 additions and 11 deletions

View file

@ -2048,6 +2048,11 @@ grid_render(struct terminal *term)
term->is_searching != term->render.was_searching ||
term->render.margins)
{
if (buf->age > 0) {
LOG_DBG("compositor double buffers (age=%d): last=%p, cur=%p",
buf->age, (void*)term->render.last_buf, (void*)buf);
}
if (term->render.last_buf != NULL &&
term->render.last_buf->width == buf->width &&
term->render.last_buf->height == buf->height &&
@ -2080,6 +2085,7 @@ grid_render(struct terminal *term)
term->render.was_searching = term->is_searching;
}
buf->age = 0;
tll_foreach(term->grid->scroll_damage, it) {
switch (it->item.type) {
case DAMAGE_SCROLL:

37
shm.c
View file

@ -30,6 +30,8 @@
#define TIME_SCROLL 0
#define FORCED_DOUBLE_BUFFERING 0
/*
* Maximum memfd size allowed.
*
@ -222,6 +224,8 @@ shm_get_buffer(struct wl_shm *shm, int width, int height, unsigned long cookie,
tll_remove(buffers, it);
}
struct buffer *cached = NULL;
tll_foreach(buffers, it) {
if (it->item.width != width)
continue;
@ -230,16 +234,27 @@ shm_get_buffer(struct wl_shm *shm, int width, int height, unsigned long cookie,
if (it->item.cookie != cookie)
continue;
if (!it->item.busy) {
LOG_DBG("cookie=%lx: re-using buffer from cache (buf=%p)",
cookie, (void *)&it->item);
it->item.busy = true;
it->item.purge = false;
xassert(it->item.pix_instances == pix_instances);
return &it->item;
}
if (it->item.busy)
it->item.age++;
else
#if FORCED_DOUBLE_BUFFERING
if (it->item.age == 0)
it->item.age++;
else
#endif
{
LOG_DBG("cookie=%lx: re-using buffer from cache (buf=%p)",
cookie, (void *)&it->item);
it->item.busy = true;
it->item.purge = false;
xassert(it->item.pix_instances == pix_instances);
cached = &it->item;
}
}
if (cached != NULL)
return cached;
/* Purge old buffers associated with this cookie */
tll_foreach(buffers, it) {
if (it->item.cookie != cookie)
@ -376,9 +391,9 @@ shm_get_buffer(struct wl_shm *shm, int width, int height, unsigned long cookie,
.scrollable = scrollable,
.real_mmapped = real_mmapped,
.mmap_size = memfd_size,
.offset = 0}
)
);
.offset = 0,
.age = 0,
}));
struct buffer *ret = &tll_back(buffers);
if (!instantiate_offset(shm, ret, initial_offset))

2
shm.h
View file

@ -32,6 +32,8 @@ struct buffer {
bool scrollable;
bool purge; /* True if this buffer should be destroyed */
int age;
};
struct buffer *shm_get_buffer(