mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
shm: refactor: move away from a single, global, buffer list
Up until now, *all* buffers have been tracked in a single, global buffer list. We've used 'cookies' to separate buffers from different contexts (so that shm_get_buffer() doesn't try to re-use e.g. a search-box buffer for the main grid). This patch refactors this, and completely removes the global list. Instead of cookies, we now use 'chains'. A chain tracks both the properties to apply to newly created buffers (scrollable, number of pixman instances to instantiate etc), as well as the instantiated buffers themselves. This means there's strictly speaking not much use for shm_fini() anymore, since its up to the chain owner to call shm_chain_free(), which will also purge all buffers. However, since purging a buffer may be deferred, if the buffer is owned by the compositor at the time of the call to shm_purge() or shm_chain_free(), we still keep a global 'deferred' list, on to which deferred buffers are pushed. shm_fini() iterates this list and destroys the buffers _even_ if they are still owned by the compositor. This only happens at program termination, and not when destroying a terminal instance. I.e. closing a window in a “foot --server” does *not* trigger this. Each terminal instatiates a number of chains, and these chains are destroyed when the terminal instance is destroyed. Note that some buffers may be put on the deferred list, as mentioned above.
This commit is contained in:
parent
4efb34927e
commit
53851e13ec
6 changed files with 190 additions and 164 deletions
49
render.c
49
render.c
|
|
@ -943,7 +943,7 @@ grid_render_scroll(struct terminal *term, struct buffer *buf,
|
||||||
|
|
||||||
if (try_shm_scroll) {
|
if (try_shm_scroll) {
|
||||||
did_shm_scroll = shm_scroll(
|
did_shm_scroll = shm_scroll(
|
||||||
term->wl->shm, buf, dmg->lines * term->cell_height,
|
buf, dmg->lines * term->cell_height,
|
||||||
term->margins.top, dmg->region.start * term->cell_height,
|
term->margins.top, dmg->region.start * term->cell_height,
|
||||||
term->margins.bottom, (term->rows - dmg->region.end) * term->cell_height);
|
term->margins.bottom, (term->rows - dmg->region.end) * term->cell_height);
|
||||||
}
|
}
|
||||||
|
|
@ -1008,7 +1008,7 @@ grid_render_scroll_reverse(struct terminal *term, struct buffer *buf,
|
||||||
|
|
||||||
if (try_shm_scroll) {
|
if (try_shm_scroll) {
|
||||||
did_shm_scroll = shm_scroll(
|
did_shm_scroll = shm_scroll(
|
||||||
term->wl->shm, buf, -dmg->lines * term->cell_height,
|
buf, -dmg->lines * term->cell_height,
|
||||||
term->margins.top, dmg->region.start * term->cell_height,
|
term->margins.top, dmg->region.start * term->cell_height,
|
||||||
term->margins.bottom, (term->rows - dmg->region.end) * term->cell_height);
|
term->margins.bottom, (term->rows - dmg->region.end) * term->cell_height);
|
||||||
}
|
}
|
||||||
|
|
@ -1587,9 +1587,8 @@ render_csd_title(struct terminal *term)
|
||||||
xassert(info.width % term->scale == 0);
|
xassert(info.width % term->scale == 0);
|
||||||
xassert(info.height % term->scale == 0);
|
xassert(info.height % term->scale == 0);
|
||||||
|
|
||||||
unsigned long cookie = shm_cookie_csd(term, CSD_SURF_TITLE);
|
struct buffer_chain *chain = term->render.chains.csd[CSD_SURF_TITLE];
|
||||||
struct buffer *buf = shm_get_buffer(
|
struct buffer *buf = shm_get_buffer(chain, info.width, info.height);
|
||||||
term->wl->shm, info.width, info.height, cookie, false, 1);
|
|
||||||
|
|
||||||
uint32_t _color = term->conf->colors.fg;
|
uint32_t _color = term->conf->colors.fg;
|
||||||
uint16_t alpha = 0xffff;
|
uint16_t alpha = 0xffff;
|
||||||
|
|
@ -1622,9 +1621,8 @@ render_csd_border(struct terminal *term, enum csd_surface surf_idx)
|
||||||
xassert(info.width % term->scale == 0);
|
xassert(info.width % term->scale == 0);
|
||||||
xassert(info.height % term->scale == 0);
|
xassert(info.height % term->scale == 0);
|
||||||
|
|
||||||
unsigned long cookie = shm_cookie_csd(term, surf_idx);
|
struct buffer_chain *chain = term->render.chains.csd[surf_idx];
|
||||||
struct buffer *buf = shm_get_buffer(
|
struct buffer *buf = shm_get_buffer(chain, info.width, info.height);
|
||||||
term->wl->shm, info.width, info.height, cookie, false, 1);
|
|
||||||
|
|
||||||
pixman_color_t color = color_hex_to_pixman_with_alpha(0, 0);
|
pixman_color_t color = color_hex_to_pixman_with_alpha(0, 0);
|
||||||
render_csd_part(term, surf, buf, info.width, info.height, &color);
|
render_csd_part(term, surf, buf, info.width, info.height, &color);
|
||||||
|
|
@ -1808,9 +1806,8 @@ render_csd_button(struct terminal *term, enum csd_surface surf_idx)
|
||||||
xassert(info.width % term->scale == 0);
|
xassert(info.width % term->scale == 0);
|
||||||
xassert(info.height % term->scale == 0);
|
xassert(info.height % term->scale == 0);
|
||||||
|
|
||||||
unsigned long cookie = shm_cookie_csd(term, surf_idx);
|
struct buffer_chain *chain = term->render.chains.csd[surf_idx];
|
||||||
struct buffer *buf = shm_get_buffer(
|
struct buffer *buf = shm_get_buffer(chain, info.width, info.height);
|
||||||
term->wl->shm, info.width, info.height, cookie, false, 1);
|
|
||||||
|
|
||||||
uint32_t _color;
|
uint32_t _color;
|
||||||
uint16_t alpha = 0xffff;
|
uint16_t alpha = 0xffff;
|
||||||
|
|
@ -2084,9 +2081,8 @@ render_scrollback_position(struct terminal *term)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long cookie = shm_cookie_scrollback_indicator(term);
|
struct buffer_chain *chain = term->render.chains.scrollback_indicator;
|
||||||
struct buffer *buf = shm_get_buffer(
|
struct buffer *buf = shm_get_buffer(chain, width, height);
|
||||||
term->wl->shm, width, height, cookie, false, 1);
|
|
||||||
|
|
||||||
wl_subsurface_set_position(
|
wl_subsurface_set_position(
|
||||||
win->scrollback_indicator.sub, x / scale, y / scale);
|
win->scrollback_indicator.sub, x / scale, y / scale);
|
||||||
|
|
@ -2117,9 +2113,8 @@ render_render_timer(struct terminal *term, struct timeval render_time)
|
||||||
const int height =
|
const int height =
|
||||||
(2 * margin + term->cell_height + scale - 1) / scale * scale;
|
(2 * margin + term->cell_height + scale - 1) / scale * scale;
|
||||||
|
|
||||||
unsigned long cookie = shm_cookie_render_timer(term);
|
struct buffer_chain *chain = term->render.chains.render_timer;
|
||||||
struct buffer *buf = shm_get_buffer(
|
struct buffer *buf = shm_get_buffer(chain, width, height);
|
||||||
term->wl->shm, width, height, cookie, false, 1);
|
|
||||||
|
|
||||||
wl_subsurface_set_position(
|
wl_subsurface_set_position(
|
||||||
win->render_timer.sub,
|
win->render_timer.sub,
|
||||||
|
|
@ -2292,9 +2287,8 @@ grid_render(struct terminal *term)
|
||||||
xassert(term->width > 0);
|
xassert(term->width > 0);
|
||||||
xassert(term->height > 0);
|
xassert(term->height > 0);
|
||||||
|
|
||||||
unsigned long cookie = shm_cookie_grid(term);
|
struct buffer_chain *chain = term->render.chains.grid;
|
||||||
struct buffer *buf = shm_get_buffer(
|
struct buffer *buf = shm_get_buffer(chain, term->width, term->height);
|
||||||
term->wl->shm, term->width, term->height, cookie, true, 1 + term->render.workers.count);
|
|
||||||
|
|
||||||
/* Dirty old and current cursor cell, to ensure they’re repainted */
|
/* Dirty old and current cursor cell, to ensure they’re repainted */
|
||||||
dirty_old_cursor(term);
|
dirty_old_cursor(term);
|
||||||
|
|
@ -2626,8 +2620,8 @@ render_search_box(struct terminal *term)
|
||||||
const size_t visible_cells = (visible_width - 2 * margin) / term->cell_width;
|
const size_t visible_cells = (visible_width - 2 * margin) / term->cell_width;
|
||||||
size_t glyph_offset = term->render.search_glyph_offset;
|
size_t glyph_offset = term->render.search_glyph_offset;
|
||||||
|
|
||||||
unsigned long cookie = shm_cookie_search(term);
|
struct buffer_chain *chain = term->render.chains.search;
|
||||||
struct buffer *buf = shm_get_buffer(term->wl->shm, width, height, cookie, false, 1);
|
struct buffer *buf = shm_get_buffer(chain, width, height);
|
||||||
|
|
||||||
pixman_region32_t clip;
|
pixman_region32_t clip;
|
||||||
pixman_region32_init_rect(&clip, 0, 0, width, height);
|
pixman_region32_init_rect(&clip, 0, 0, width, height);
|
||||||
|
|
@ -2936,7 +2930,8 @@ render_urls(struct terminal *term)
|
||||||
} info[tll_length(win->urls)];
|
} info[tll_length(win->urls)];
|
||||||
|
|
||||||
/* For shm_get_many() */
|
/* For shm_get_many() */
|
||||||
struct buffer_description shm_desc[tll_length(win->urls)];
|
int widths[tll_length(win->urls)];
|
||||||
|
int heights[tll_length(win->urls)];
|
||||||
|
|
||||||
size_t render_count = 0;
|
size_t render_count = 0;
|
||||||
|
|
||||||
|
|
@ -3066,15 +3061,15 @@ render_urls(struct terminal *term)
|
||||||
info[render_count].x = x;
|
info[render_count].x = x;
|
||||||
info[render_count].y = y;
|
info[render_count].y = y;
|
||||||
|
|
||||||
shm_desc[render_count].width = width;
|
widths[render_count] = width;
|
||||||
shm_desc[render_count].height = height;
|
heights[render_count] = height;
|
||||||
shm_desc[render_count].cookie = shm_cookie_url(url);
|
|
||||||
|
|
||||||
render_count++;
|
render_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct buffer_chain *chain = term->render.chains.url;
|
||||||
struct buffer *bufs[render_count];
|
struct buffer *bufs[render_count];
|
||||||
shm_get_many(term->wl->shm, render_count, shm_desc, bufs, 1);
|
shm_get_many(chain, render_count, widths, heights, bufs);
|
||||||
|
|
||||||
uint32_t fg = term->conf->colors.use_custom.jump_label
|
uint32_t fg = term->conf->colors.use_custom.jump_label
|
||||||
? term->conf->colors.jump_label.fg
|
? term->conf->colors.jump_label.fg
|
||||||
|
|
|
||||||
215
shm.c
215
shm.c
|
|
@ -68,21 +68,28 @@ struct buffer_pool {
|
||||||
size_t ref_count;
|
size_t ref_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct buffer_chain;
|
||||||
struct buffer_private {
|
struct buffer_private {
|
||||||
struct buffer public;
|
struct buffer public;
|
||||||
|
struct buffer_chain *chain;
|
||||||
|
|
||||||
size_t ref_count;
|
size_t ref_count;
|
||||||
size_t size;
|
|
||||||
bool busy; /* Owned by compositor */
|
bool busy; /* Owned by compositor */
|
||||||
|
|
||||||
unsigned long cookie;
|
|
||||||
struct buffer_pool *pool;
|
struct buffer_pool *pool;
|
||||||
off_t offset; /* Offset into memfd where data begins */
|
off_t offset; /* Offset into memfd where data begins */
|
||||||
|
size_t size;
|
||||||
|
|
||||||
bool scrollable;
|
bool scrollable;
|
||||||
};
|
};
|
||||||
|
|
||||||
static tll(struct buffer_private *) buffers;
|
struct buffer_chain {
|
||||||
|
tll(struct buffer_private *) bufs;
|
||||||
|
struct wl_shm *shm;
|
||||||
|
size_t pix_instances;
|
||||||
|
bool scrollable;
|
||||||
|
};
|
||||||
|
|
||||||
static tll(struct buffer_private *) deferred;
|
static tll(struct buffer_private *) deferred;
|
||||||
|
|
||||||
#undef MEASURE_SHM_ALLOCS
|
#undef MEASURE_SHM_ALLOCS
|
||||||
|
|
@ -151,7 +158,7 @@ buffer_destroy(struct buffer_private *buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
buffer_unref_no_remove_from_cache(struct buffer_private *buf)
|
buffer_unref_no_remove_from_chain(struct buffer_private *buf)
|
||||||
{
|
{
|
||||||
xassert(buf->ref_count > 0);
|
xassert(buf->ref_count > 0);
|
||||||
buf->ref_count--;
|
buf->ref_count--;
|
||||||
|
|
@ -169,34 +176,13 @@ buffer_unref_no_remove_from_cache(struct buffer_private *buf)
|
||||||
void
|
void
|
||||||
shm_fini(void)
|
shm_fini(void)
|
||||||
{
|
{
|
||||||
size_t busy_count UNUSED = 0;
|
LOG_DBG("deferred buffers: %zu", tll_length(deferred));
|
||||||
size_t non_busy_count UNUSED = 0;
|
|
||||||
|
|
||||||
tll_foreach(buffers, it) {
|
|
||||||
if (it->item->busy)
|
|
||||||
busy_count++;
|
|
||||||
else
|
|
||||||
non_busy_count++;
|
|
||||||
|
|
||||||
buffer_destroy(it->item);
|
|
||||||
tll_remove(buffers, it);
|
|
||||||
}
|
|
||||||
|
|
||||||
xassert(busy_count == 0);
|
|
||||||
busy_count = tll_length(deferred);
|
|
||||||
|
|
||||||
tll_foreach(deferred, it) {
|
tll_foreach(deferred, it) {
|
||||||
buffer_destroy(it->item);
|
buffer_destroy(it->item);
|
||||||
tll_remove(deferred, it);
|
tll_remove(deferred, it);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DBG("buffers left: busy=%zu, non-busy=%zu", busy_count, non_busy_count);
|
|
||||||
|
|
||||||
if (non_busy_count > 0) {
|
|
||||||
BUG("%zu non-busy buffers remaining (%zu buffers in total)",
|
|
||||||
non_busy_count, busy_count + non_busy_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(MEASURE_SHM_ALLOCS) && MEASURE_SHM_ALLOCS
|
#if defined(MEASURE_SHM_ALLOCS) && MEASURE_SHM_ALLOCS
|
||||||
LOG_INFO("max total allocations was: %zu MB", max_alloced / 1024 / 1024);
|
LOG_INFO("max total allocations was: %zu MB", max_alloced / 1024 / 1024);
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -207,27 +193,25 @@ buffer_release(void *data, struct wl_buffer *wl_buffer)
|
||||||
{
|
{
|
||||||
struct buffer_private *buffer = data;
|
struct buffer_private *buffer = data;
|
||||||
|
|
||||||
LOG_DBG("release: cookie=%lx (buf=%p, total buffer count: %zu)",
|
|
||||||
buffer->cookie, (void *)buffer, tll_length(buffers));
|
|
||||||
|
|
||||||
xassert(buffer->public.wl_buf == wl_buffer);
|
xassert(buffer->public.wl_buf == wl_buffer);
|
||||||
xassert(buffer->busy);
|
xassert(buffer->busy);
|
||||||
buffer->busy = false;
|
buffer->busy = false;
|
||||||
|
|
||||||
if (buffer->ref_count == 0) {
|
if (buffer->ref_count == 0) {
|
||||||
LOG_WARN("deferred delete");
|
|
||||||
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
tll_foreach(deferred, it) {
|
tll_foreach(deferred, it) {
|
||||||
if (it->item == buffer) {
|
if (it->item == buffer) {
|
||||||
found = true;
|
found = true;
|
||||||
buffer_destroy(buffer);
|
|
||||||
tll_remove(deferred, it);
|
tll_remove(deferred, it);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buffer_destroy(buffer);
|
||||||
|
|
||||||
xassert(found);
|
xassert(found);
|
||||||
|
if (!found)
|
||||||
|
LOG_WARN("deferred delete: buffer not on the 'deferred' list");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -255,7 +239,7 @@ page_size(void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
instantiate_offset(struct wl_shm *shm, struct buffer_private *buf, off_t new_offset)
|
instantiate_offset(struct buffer_private *buf, off_t new_offset)
|
||||||
{
|
{
|
||||||
xassert(buf->public.data == NULL);
|
xassert(buf->public.data == NULL);
|
||||||
xassert(buf->public.pix == NULL);
|
xassert(buf->public.pix == NULL);
|
||||||
|
|
@ -314,12 +298,11 @@ err:
|
||||||
}
|
}
|
||||||
|
|
||||||
static void NOINLINE
|
static void NOINLINE
|
||||||
get_new_buffers(struct wl_shm *shm, size_t count,
|
get_new_buffers(struct buffer_chain *chain, size_t count,
|
||||||
struct buffer_description info[static count],
|
int widths[static count], int heights[static count],
|
||||||
struct buffer *bufs[static count],
|
struct buffer *bufs[static count], bool immediate_purge)
|
||||||
size_t pix_instances, bool scrollable, bool immediate_purge)
|
|
||||||
{
|
{
|
||||||
xassert(count == 1 || !scrollable);
|
xassert(count == 1 || !chain->scrollable);
|
||||||
/*
|
/*
|
||||||
* No existing buffer available. Create a new one by:
|
* No existing buffer available. Create a new one by:
|
||||||
*
|
*
|
||||||
|
|
@ -335,8 +318,8 @@ get_new_buffers(struct wl_shm *shm, size_t count,
|
||||||
|
|
||||||
size_t total_size = 0;
|
size_t total_size = 0;
|
||||||
for (size_t i = 0; i < count; i++) {
|
for (size_t i = 0; i < count; i++) {
|
||||||
stride[i] = stride_for_format_and_width(PIXMAN_a8r8g8b8, info[i].width);
|
stride[i] = stride_for_format_and_width(PIXMAN_a8r8g8b8, widths[i]);
|
||||||
sizes[i] = stride[i] * info[i].height;
|
sizes[i] = stride[i] * heights[i];
|
||||||
total_size += sizes[i];
|
total_size += sizes[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -363,14 +346,18 @@ get_new_buffers(struct wl_shm *shm, size_t count,
|
||||||
}
|
}
|
||||||
|
|
||||||
#if __SIZEOF_POINTER__ == 8
|
#if __SIZEOF_POINTER__ == 8
|
||||||
off_t offset = scrollable && max_pool_size > 0 ? (max_pool_size / 4) & ~(page_size() - 1) : 0;
|
off_t offset = chain->scrollable && max_pool_size > 0
|
||||||
off_t memfd_size = scrollable && max_pool_size > 0 ? max_pool_size : total_size;
|
? (max_pool_size / 4) & ~(page_size() - 1)
|
||||||
|
: 0;
|
||||||
|
off_t memfd_size = chain->scrollable && max_pool_size > 0
|
||||||
|
? max_pool_size
|
||||||
|
: total_size;
|
||||||
#else
|
#else
|
||||||
off_t offset = 0;
|
off_t offset = 0;
|
||||||
off_t memfd_size = total_size;
|
off_t memfd_size = total_size;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
xassert(scrollable || (offset == 0 && memfd_size == total_size));
|
xassert(chain->scrollable || (offset == 0 && memfd_size == total_size));
|
||||||
|
|
||||||
LOG_DBG("memfd-size: %lu, initial offset: %lu", memfd_size, offset);
|
LOG_DBG("memfd-size: %lu, initial offset: %lu", memfd_size, offset);
|
||||||
|
|
||||||
|
|
@ -397,10 +384,10 @@ get_new_buffers(struct wl_shm *shm, size_t count,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scrollable && !can_punch_hole) {
|
if (chain->scrollable && !can_punch_hole) {
|
||||||
offset = 0;
|
offset = 0;
|
||||||
memfd_size = total_size;
|
memfd_size = total_size;
|
||||||
scrollable = false;
|
chain->scrollable = false;
|
||||||
|
|
||||||
if (ftruncate(pool_fd, memfd_size) < 0) {
|
if (ftruncate(pool_fd, memfd_size) < 0) {
|
||||||
LOG_ERRNO("failed to set size of SHM backing memory file");
|
LOG_ERRNO("failed to set size of SHM backing memory file");
|
||||||
|
|
@ -428,13 +415,13 @@ get_new_buffers(struct wl_shm *shm, size_t count,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
wl_pool = wl_shm_create_pool(shm, pool_fd, memfd_size);
|
wl_pool = wl_shm_create_pool(chain->shm, pool_fd, memfd_size);
|
||||||
if (wl_pool == NULL) {
|
if (wl_pool == NULL) {
|
||||||
LOG_ERR("failed to create SHM pool");
|
LOG_ERR("failed to create SHM pool");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
pool = malloc(sizeof(*pool));
|
pool = xmalloc(sizeof(*pool));
|
||||||
if (pool == NULL) {
|
if (pool == NULL) {
|
||||||
LOG_ERRNO("failed to allocate buffer pool");
|
LOG_ERRNO("failed to allocate buffer pool");
|
||||||
goto err;
|
goto err;
|
||||||
|
|
@ -454,22 +441,22 @@ get_new_buffers(struct wl_shm *shm, size_t count,
|
||||||
struct buffer_private *buf = xmalloc(sizeof(*buf));
|
struct buffer_private *buf = xmalloc(sizeof(*buf));
|
||||||
*buf = (struct buffer_private){
|
*buf = (struct buffer_private){
|
||||||
.public = {
|
.public = {
|
||||||
.width = info[i].width,
|
.width = widths[i],
|
||||||
.height = info[i].height,
|
.height = heights[i],
|
||||||
.stride = stride[i],
|
.stride = stride[i],
|
||||||
.pix_instances = pix_instances,
|
.pix_instances = chain->pix_instances,
|
||||||
.age = 1234, /* Force a full repaint */
|
.age = 1234, /* Force a full repaint */
|
||||||
},
|
},
|
||||||
.cookie = info[i].cookie,
|
.chain = chain,
|
||||||
.ref_count = immediate_purge ? 0 : 1,
|
.ref_count = immediate_purge ? 0 : 1,
|
||||||
.size = sizes[i],
|
|
||||||
.busy = true,
|
.busy = true,
|
||||||
.pool = pool,
|
.pool = pool,
|
||||||
.scrollable = scrollable,
|
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
|
.size = sizes[i],
|
||||||
|
.scrollable = chain->scrollable,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!instantiate_offset(shm, buf, offset)) {
|
if (!instantiate_offset(buf, offset)) {
|
||||||
free(buf);
|
free(buf);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
@ -477,7 +464,7 @@ get_new_buffers(struct wl_shm *shm, size_t count,
|
||||||
if (immediate_purge)
|
if (immediate_purge)
|
||||||
tll_push_front(deferred, buf);
|
tll_push_front(deferred, buf);
|
||||||
else
|
else
|
||||||
tll_push_front(buffers, buf);
|
tll_push_front(chain->bufs, buf);
|
||||||
|
|
||||||
pixman_region32_init(&buf->public.dirty);
|
pixman_region32_init(&buf->public.dirty);
|
||||||
pool->ref_count++;
|
pool->ref_count++;
|
||||||
|
|
@ -518,28 +505,24 @@ err:
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
shm_get_many(struct wl_shm *shm, size_t count,
|
shm_get_many(struct buffer_chain *chain, size_t count,
|
||||||
struct buffer_description info[static count],
|
int widths[static count], int heights[static count],
|
||||||
struct buffer *bufs[static count],
|
struct buffer *bufs[static count])
|
||||||
size_t pix_instances)
|
|
||||||
{
|
{
|
||||||
get_new_buffers(shm, count, info, bufs, pix_instances, false, true);
|
get_new_buffers(chain, count, widths, heights, bufs, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct buffer *
|
struct buffer *
|
||||||
shm_get_buffer(struct wl_shm *shm, int width, int height, unsigned long cookie,
|
shm_get_buffer(struct buffer_chain *chain, int width, int height)
|
||||||
bool scrollable, size_t pix_instances)
|
|
||||||
{
|
{
|
||||||
struct buffer_private *cached = NULL;
|
struct buffer_private *cached = NULL;
|
||||||
tll_foreach(buffers, it) {
|
tll_foreach(chain->bufs, it) {
|
||||||
struct buffer_private *buf = it->item;
|
struct buffer_private *buf = it->item;
|
||||||
|
|
||||||
if (buf->public.width != width)
|
if (buf->public.width != width)
|
||||||
continue;
|
continue;
|
||||||
if (buf->public.height != height)
|
if (buf->public.height != height)
|
||||||
continue;
|
continue;
|
||||||
if (buf->cookie != cookie)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (buf->busy)
|
if (buf->busy)
|
||||||
buf->public.age++;
|
buf->public.age++;
|
||||||
|
|
@ -551,13 +534,12 @@ shm_get_buffer(struct wl_shm *shm, int width, int height, unsigned long cookie,
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (cached == NULL) {
|
if (cached == NULL) {
|
||||||
LOG_DBG("cookie=%lx: re-using buffer from cache (buf=%p)",
|
LOG_DBG("re-using buffer %p from cache", (void *)buf);
|
||||||
cookie, (void *)buf);
|
|
||||||
buf->busy = true;
|
buf->busy = true;
|
||||||
pixman_region32_clear(&buf->public.dirty);
|
pixman_region32_clear(&buf->public.dirty);
|
||||||
free(buf->public.scroll_damage);
|
free(buf->public.scroll_damage);
|
||||||
buf->public.scroll_damage = NULL;
|
buf->public.scroll_damage = NULL;
|
||||||
xassert(buf->public.pix_instances == pix_instances);
|
xassert(buf->public.pix_instances == chain->pix_instances);
|
||||||
cached = it->item;
|
cached = it->item;
|
||||||
} else {
|
} else {
|
||||||
/* We have multiple buffers eligible for
|
/* We have multiple buffers eligible for
|
||||||
|
|
@ -567,8 +549,8 @@ shm_get_buffer(struct wl_shm *shm, int width, int height, unsigned long cookie,
|
||||||
shm_unref(&cached->public);
|
shm_unref(&cached->public);
|
||||||
cached = buf;
|
cached = buf;
|
||||||
} else {
|
} else {
|
||||||
if (buffer_unref_no_remove_from_cache(buf))
|
if (buffer_unref_no_remove_from_chain(buf))
|
||||||
tll_remove(buffers, it);
|
tll_remove(chain->bufs, it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -578,23 +560,19 @@ shm_get_buffer(struct wl_shm *shm, int width, int height, unsigned long cookie,
|
||||||
return &cached->public;
|
return &cached->public;
|
||||||
|
|
||||||
/* Mark old buffers associated with this cookie for purging */
|
/* Mark old buffers associated with this cookie for purging */
|
||||||
tll_foreach(buffers, it) {
|
tll_foreach(chain->bufs, it) {
|
||||||
struct buffer_private *buf = it->item;
|
struct buffer_private *buf = it->item;
|
||||||
|
|
||||||
if (buf->cookie != cookie)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (buf->public.width == width && buf->public.height == height)
|
if (buf->public.width == width && buf->public.height == height)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
LOG_DBG("cookie=%lx: marking buffer %p for purging", cookie, (void *)buf);
|
LOG_DBG("marking buffer %p for purging", (void *)buf);
|
||||||
if (buffer_unref_no_remove_from_cache(buf))
|
if (buffer_unref_no_remove_from_chain(buf))
|
||||||
tll_remove(buffers, it);
|
tll_remove(chain->bufs, it);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct buffer *ret;
|
struct buffer *ret;
|
||||||
get_new_buffers(shm, 1, &(struct buffer_description){width, height, cookie},
|
get_new_buffers(chain, 1, &width, &height, &ret, false);
|
||||||
&ret, pix_instances, scrollable, false);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -612,7 +590,7 @@ shm_can_scroll(const struct buffer *_buf)
|
||||||
|
|
||||||
#if __SIZEOF_POINTER__ == 8 && defined(FALLOC_FL_PUNCH_HOLE)
|
#if __SIZEOF_POINTER__ == 8 && defined(FALLOC_FL_PUNCH_HOLE)
|
||||||
static bool
|
static bool
|
||||||
wrap_buffer(struct wl_shm *shm, struct buffer_private *buf, off_t new_offset)
|
wrap_buffer(struct buffer_private *buf, off_t new_offset)
|
||||||
{
|
{
|
||||||
struct buffer_pool *pool = buf->pool;
|
struct buffer_pool *pool = buf->pool;
|
||||||
xassert(pool->ref_count == 1);
|
xassert(pool->ref_count == 1);
|
||||||
|
|
@ -649,11 +627,11 @@ wrap_buffer(struct wl_shm *shm, struct buffer_private *buf, off_t new_offset)
|
||||||
|
|
||||||
/* Re-instantiate pixman+wl_buffer+raw pointersw */
|
/* Re-instantiate pixman+wl_buffer+raw pointersw */
|
||||||
buffer_destroy_dont_close(&buf->public);
|
buffer_destroy_dont_close(&buf->public);
|
||||||
return instantiate_offset(shm, buf, new_offset);
|
return instantiate_offset(buf, new_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
shm_scroll_forward(struct wl_shm *shm, struct buffer_private *buf, int rows,
|
shm_scroll_forward(struct buffer_private *buf, int rows,
|
||||||
int top_margin, int top_keep_rows,
|
int top_margin, int top_keep_rows,
|
||||||
int bottom_margin, int bottom_keep_rows)
|
int bottom_margin, int bottom_keep_rows)
|
||||||
{
|
{
|
||||||
|
|
@ -675,7 +653,7 @@ shm_scroll_forward(struct wl_shm *shm, struct buffer_private *buf, int rows,
|
||||||
|
|
||||||
if (buf->offset + diff + buf->size > max_pool_size) {
|
if (buf->offset + diff + buf->size > max_pool_size) {
|
||||||
LOG_DBG("memfd offset wrap around");
|
LOG_DBG("memfd offset wrap around");
|
||||||
if (!wrap_buffer(shm, buf, 0))
|
if (!wrap_buffer(buf, 0))
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -684,6 +662,7 @@ shm_scroll_forward(struct wl_shm *shm, struct buffer_private *buf, int rows,
|
||||||
xassert(new_offset + buf->size <= max_pool_size);
|
xassert(new_offset + buf->size <= max_pool_size);
|
||||||
|
|
||||||
#if TIME_SCROLL
|
#if TIME_SCROLL
|
||||||
|
struct timeval tot;
|
||||||
struct timeval time1;
|
struct timeval time1;
|
||||||
gettimeofday(&time1, NULL);
|
gettimeofday(&time1, NULL);
|
||||||
|
|
||||||
|
|
@ -731,7 +710,7 @@ shm_scroll_forward(struct wl_shm *shm, struct buffer_private *buf, int rows,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Re-instantiate pixman+wl_buffer+raw pointersw */
|
/* Re-instantiate pixman+wl_buffer+raw pointersw */
|
||||||
bool ret = instantiate_offset(shm, buf, new_offset);
|
bool ret = instantiate_offset(buf, new_offset);
|
||||||
|
|
||||||
#if TIME_SCROLL
|
#if TIME_SCROLL
|
||||||
struct timeval time4;
|
struct timeval time4;
|
||||||
|
|
@ -768,7 +747,7 @@ err:
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
shm_scroll_reverse(struct wl_shm *shm, struct buffer_private *buf, int rows,
|
shm_scroll_reverse(struct buffer_private *buf, int rows,
|
||||||
int top_margin, int top_keep_rows,
|
int top_margin, int top_keep_rows,
|
||||||
int bottom_margin, int bottom_keep_rows)
|
int bottom_margin, int bottom_keep_rows)
|
||||||
{
|
{
|
||||||
|
|
@ -780,7 +759,7 @@ shm_scroll_reverse(struct wl_shm *shm, struct buffer_private *buf, int rows,
|
||||||
const off_t diff = rows * buf->public.stride;
|
const off_t diff = rows * buf->public.stride;
|
||||||
if (diff > buf->offset) {
|
if (diff > buf->offset) {
|
||||||
LOG_DBG("memfd offset reverse wrap-around");
|
LOG_DBG("memfd offset reverse wrap-around");
|
||||||
if (!wrap_buffer(shm, buf, (max_pool_size - buf->size) & ~(page_size() - 1)))
|
if (!wrap_buffer(buf, (max_pool_size - buf->size) & ~(page_size() - 1)))
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -837,7 +816,7 @@ shm_scroll_reverse(struct wl_shm *shm, struct buffer_private *buf, int rows,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Re-instantiate pixman+wl_buffer+raw pointers */
|
/* Re-instantiate pixman+wl_buffer+raw pointers */
|
||||||
bool ret = instantiate_offset(shm, buf, new_offset);
|
bool ret = instantiate_offset(buf, new_offset);
|
||||||
|
|
||||||
#if TIME_SCROLL
|
#if TIME_SCROLL
|
||||||
struct timeval time3;
|
struct timeval time3;
|
||||||
|
|
@ -873,7 +852,7 @@ err:
|
||||||
#endif /* FALLOC_FL_PUNCH_HOLE */
|
#endif /* FALLOC_FL_PUNCH_HOLE */
|
||||||
|
|
||||||
bool
|
bool
|
||||||
shm_scroll(struct wl_shm *shm, struct buffer *_buf, int rows,
|
shm_scroll(struct buffer *_buf, int rows,
|
||||||
int top_margin, int top_keep_rows,
|
int top_margin, int top_keep_rows,
|
||||||
int bottom_margin, int bottom_keep_rows)
|
int bottom_margin, int bottom_keep_rows)
|
||||||
{
|
{
|
||||||
|
|
@ -885,27 +864,22 @@ shm_scroll(struct wl_shm *shm, struct buffer *_buf, int rows,
|
||||||
|
|
||||||
xassert(rows != 0);
|
xassert(rows != 0);
|
||||||
return rows > 0
|
return rows > 0
|
||||||
? shm_scroll_forward(shm, buf, rows, top_margin, top_keep_rows, bottom_margin, bottom_keep_rows)
|
? shm_scroll_forward(buf, rows, top_margin, top_keep_rows, bottom_margin, bottom_keep_rows)
|
||||||
: shm_scroll_reverse(shm, buf, -rows, top_margin, top_keep_rows, bottom_margin, bottom_keep_rows);
|
: shm_scroll_reverse(buf, -rows, top_margin, top_keep_rows, bottom_margin, bottom_keep_rows);
|
||||||
#else
|
#else
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
shm_purge(struct wl_shm *shm, unsigned long cookie)
|
shm_purge(struct buffer_chain *chain)
|
||||||
{
|
{
|
||||||
LOG_DBG("cookie=%lx: purging all buffers", cookie);
|
LOG_DBG("chain: %p: purging all buffers", (void *)chain);
|
||||||
|
|
||||||
/* Purge old buffers associated with this cookie */
|
/* Purge old buffers associated with this cookie */
|
||||||
tll_foreach(buffers, it) {
|
tll_foreach(chain->bufs, it) {
|
||||||
struct buffer_private *buf = it->item;
|
if (buffer_unref_no_remove_from_chain(it->item))
|
||||||
|
tll_remove(chain->bufs, it);
|
||||||
if (buf->cookie != cookie)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (buffer_unref_no_remove_from_cache(buf))
|
|
||||||
tll_remove(buffers, it);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -923,12 +897,47 @@ shm_unref(struct buffer *_buf)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
struct buffer_private *buf = (struct buffer_private *)_buf;
|
struct buffer_private *buf = (struct buffer_private *)_buf;
|
||||||
tll_foreach(buffers, it) {
|
struct buffer_chain *chain = buf->chain;
|
||||||
|
|
||||||
|
tll_foreach(chain->bufs, it) {
|
||||||
if (it->item != buf)
|
if (it->item != buf)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (buffer_unref_no_remove_from_cache(buf))
|
if (buffer_unref_no_remove_from_chain(buf))
|
||||||
tll_remove(buffers, it);
|
tll_remove(chain->bufs, it);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
shm_chain_purge(struct buffer_chain *chain)
|
||||||
|
{
|
||||||
|
tll_foreach(chain->bufs, it) {
|
||||||
|
struct buffer_private *buf = it->item;
|
||||||
|
if (buffer_unref_no_remove_from_chain(buf))
|
||||||
|
tll_remove(chain->bufs, it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct buffer_chain *
|
||||||
|
shm_chain_new(struct wl_shm *shm, bool scrollable, size_t pix_instances)
|
||||||
|
{
|
||||||
|
struct buffer_chain *chain = xmalloc(sizeof(*chain));
|
||||||
|
*chain = (struct buffer_chain){
|
||||||
|
.bufs = tll_init(),
|
||||||
|
.shm = shm,
|
||||||
|
.pix_instances = pix_instances,
|
||||||
|
.scrollable = scrollable,
|
||||||
|
};
|
||||||
|
return chain;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
shm_chain_free(struct buffer_chain *chain)
|
||||||
|
{
|
||||||
|
if (chain == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
shm_chain_purge(chain);
|
||||||
|
free(chain);
|
||||||
|
}
|
||||||
|
|
|
||||||
39
shm.h
39
shm.h
|
|
@ -7,6 +7,8 @@
|
||||||
#include <pixman.h>
|
#include <pixman.h>
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
|
|
||||||
|
#include <tllist.h>
|
||||||
|
|
||||||
struct damage;
|
struct damage;
|
||||||
|
|
||||||
struct buffer {
|
struct buffer {
|
||||||
|
|
@ -27,28 +29,24 @@ struct buffer {
|
||||||
pixman_region32_t dirty;
|
pixman_region32_t dirty;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct buffer_description {
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
unsigned long cookie;
|
|
||||||
};
|
|
||||||
|
|
||||||
void shm_fini(void);
|
void shm_fini(void);
|
||||||
void shm_set_max_pool_size(off_t max_pool_size);
|
void shm_set_max_pool_size(off_t max_pool_size);
|
||||||
|
|
||||||
|
struct buffer_chain;
|
||||||
|
struct buffer_chain *shm_chain_new(
|
||||||
|
struct wl_shm *shm, bool scrollable, size_t pix_instances);
|
||||||
|
void shm_chain_free(struct buffer_chain *chain);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns a single buffer.
|
* Returns a single buffer.
|
||||||
*
|
*
|
||||||
* May returned a cached buffer. If so, the buffer’s age indicates how
|
* May returned a cached buffer. If so, the buffer’s age indicates how
|
||||||
* many shm_get_buffer() calls have been made for the same
|
* many shm_get_buffer() calls have been made for the same
|
||||||
* width/height/cookie while the buffer was still busy.
|
* width/height while the buffer was still busy.
|
||||||
*
|
*
|
||||||
* A newly allocated buffer has an age of 1234.
|
* A newly allocated buffer has an age of 1234.
|
||||||
*/
|
*/
|
||||||
struct buffer *shm_get_buffer(
|
struct buffer *shm_get_buffer(struct buffer_chain *chain, int width, int height);
|
||||||
struct wl_shm *shm, int width, int height, unsigned long cookie,
|
|
||||||
bool scrollable, size_t pix_instances);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns many buffers, described by ‘info’, all sharing the same SHM
|
* Returns many buffers, described by ‘info’, all sharing the same SHM
|
||||||
* buffer pool.
|
* buffer pool.
|
||||||
|
|
@ -64,25 +62,16 @@ struct buffer *shm_get_buffer(
|
||||||
* soon as the compositor releases them.
|
* soon as the compositor releases them.
|
||||||
*/
|
*/
|
||||||
void shm_get_many(
|
void shm_get_many(
|
||||||
struct wl_shm *shm, size_t count,
|
struct buffer_chain *chain, size_t count,
|
||||||
struct buffer_description info[static count],
|
int widths[static count], int heights[static count],
|
||||||
struct buffer *bufs[static count], size_t pix_instances);
|
struct buffer *bufs[static count]);
|
||||||
|
|
||||||
bool shm_can_scroll(const struct buffer *buf);
|
bool shm_can_scroll(const struct buffer *buf);
|
||||||
bool shm_scroll(struct wl_shm *shm, struct buffer *buf, int rows,
|
bool shm_scroll(struct buffer *buf, int rows,
|
||||||
int top_margin, int top_keep_rows,
|
int top_margin, int top_keep_rows,
|
||||||
int bottom_margin, int bottom_keep_rows);
|
int bottom_margin, int bottom_keep_rows);
|
||||||
|
|
||||||
void shm_addref(struct buffer *buf);
|
void shm_addref(struct buffer *buf);
|
||||||
void shm_unref(struct buffer *buf);
|
void shm_unref(struct buffer *buf);
|
||||||
void shm_purge(struct wl_shm *shm, unsigned long cookie);
|
|
||||||
|
|
||||||
struct terminal;
|
void shm_purge(struct buffer_chain *chain);
|
||||||
static inline unsigned long shm_cookie_grid(const struct terminal *term) { return (unsigned long)((uintptr_t)term + 0); }
|
|
||||||
static inline unsigned long shm_cookie_search(const struct terminal *term) { return (unsigned long)((uintptr_t)term + 1); }
|
|
||||||
static inline unsigned long shm_cookie_scrollback_indicator(const struct terminal *term) { return (unsigned long)(uintptr_t)term + 2; }
|
|
||||||
static inline unsigned long shm_cookie_render_timer(const struct terminal *term) { return (unsigned long)(uintptr_t)term + 3; }
|
|
||||||
static inline unsigned long shm_cookie_csd(const struct terminal *term, int n) { return (unsigned long)((uintptr_t)term + 4 + (n)); }
|
|
||||||
|
|
||||||
struct url;
|
|
||||||
static inline unsigned long shm_cookie_url(const struct url *url) { return (unsigned long)(uintptr_t)url; }
|
|
||||||
|
|
|
||||||
25
terminal.c
25
terminal.c
|
|
@ -1144,6 +1144,23 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
|
||||||
.tab_stops = tll_init(),
|
.tab_stops = tll_init(),
|
||||||
.wl = wayl,
|
.wl = wayl,
|
||||||
.render = {
|
.render = {
|
||||||
|
.chains = {
|
||||||
|
.grid = shm_chain_new(wayl->shm, true, 1 + conf->render_worker_count),
|
||||||
|
.search = shm_chain_new(wayl->shm, false, 1),
|
||||||
|
.scrollback_indicator = shm_chain_new(wayl->shm, false, 1),
|
||||||
|
.render_timer = shm_chain_new(wayl->shm, false, 1),
|
||||||
|
.url = shm_chain_new(wayl->shm, false, 1),
|
||||||
|
.csd = {
|
||||||
|
[CSD_SURF_TITLE] = shm_chain_new(wayl->shm, false, 1),
|
||||||
|
[CSD_SURF_LEFT] = shm_chain_new(wayl->shm, false, 1),
|
||||||
|
[CSD_SURF_RIGHT] = shm_chain_new(wayl->shm, false, 1),
|
||||||
|
[CSD_SURF_TOP] = shm_chain_new(wayl->shm, false, 1),
|
||||||
|
[CSD_SURF_BOTTOM] = shm_chain_new(wayl->shm, false, 1),
|
||||||
|
[CSD_SURF_MINIMIZE] = shm_chain_new(wayl->shm, false, 1),
|
||||||
|
[CSD_SURF_MAXIMIZE] = shm_chain_new(wayl->shm, false, 1),
|
||||||
|
[CSD_SURF_CLOSE] = shm_chain_new(wayl->shm, false, 1),
|
||||||
|
},
|
||||||
|
},
|
||||||
.scrollback_lines = conf->scrollback.lines,
|
.scrollback_lines = conf->scrollback.lines,
|
||||||
.app_sync_updates.timer_fd = app_sync_updates_fd,
|
.app_sync_updates.timer_fd = app_sync_updates_fd,
|
||||||
.title = {
|
.title = {
|
||||||
|
|
@ -1458,7 +1475,15 @@ term_destroy(struct terminal *term)
|
||||||
sem_destroy(&term->render.workers.done);
|
sem_destroy(&term->render.workers.done);
|
||||||
xassert(tll_length(term->render.workers.queue) == 0);
|
xassert(tll_length(term->render.workers.queue) == 0);
|
||||||
tll_free(term->render.workers.queue);
|
tll_free(term->render.workers.queue);
|
||||||
|
|
||||||
shm_unref(term->render.last_buf);
|
shm_unref(term->render.last_buf);
|
||||||
|
shm_chain_free(term->render.chains.grid);
|
||||||
|
shm_chain_free(term->render.chains.search);
|
||||||
|
shm_chain_free(term->render.chains.scrollback_indicator);
|
||||||
|
shm_chain_free(term->render.chains.render_timer);
|
||||||
|
shm_chain_free(term->render.chains.url);
|
||||||
|
for (size_t i = 0; i < CSD_SURF_COUNT; i++)
|
||||||
|
shm_chain_free(term->render.chains.csd[i]);
|
||||||
|
|
||||||
tll_free(term->tab_stops);
|
tll_free(term->tab_stops);
|
||||||
|
|
||||||
|
|
|
||||||
10
terminal.h
10
terminal.h
|
|
@ -21,6 +21,7 @@
|
||||||
#include "fdm.h"
|
#include "fdm.h"
|
||||||
#include "macros.h"
|
#include "macros.h"
|
||||||
#include "reaper.h"
|
#include "reaper.h"
|
||||||
|
#include "shm.h"
|
||||||
#include "wayland.h"
|
#include "wayland.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -475,6 +476,15 @@ struct terminal {
|
||||||
enum term_surface active_surface;
|
enum term_surface active_surface;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
struct {
|
||||||
|
struct buffer_chain *grid;
|
||||||
|
struct buffer_chain *search;
|
||||||
|
struct buffer_chain *scrollback_indicator;
|
||||||
|
struct buffer_chain *render_timer;
|
||||||
|
struct buffer_chain *url;
|
||||||
|
struct buffer_chain *csd[CSD_SURF_COUNT];
|
||||||
|
} chains;
|
||||||
|
|
||||||
/* Scheduled for rendering, as soon-as-possible */
|
/* Scheduled for rendering, as soon-as-possible */
|
||||||
struct {
|
struct {
|
||||||
bool grid;
|
bool grid;
|
||||||
|
|
|
||||||
16
wayland.c
16
wayland.c
|
|
@ -52,11 +52,10 @@ static void
|
||||||
csd_destroy(struct wl_window *win)
|
csd_destroy(struct wl_window *win)
|
||||||
{
|
{
|
||||||
struct terminal *term = win->term;
|
struct terminal *term = win->term;
|
||||||
struct wl_shm *shm = term->wl->shm;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < ALEN(win->csd.surface); i++) {
|
for (size_t i = 0; i < ALEN(win->csd.surface); i++) {
|
||||||
wayl_win_subsurface_destroy(&win->csd.surface[i]);
|
wayl_win_subsurface_destroy(&win->csd.surface[i]);
|
||||||
shm_purge(shm, shm_cookie_csd(term, i));
|
shm_purge(term->render.chains.csd[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1417,7 +1416,6 @@ wayl_win_destroy(struct wl_window *win)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
struct terminal *term = win->term;
|
struct terminal *term = win->term;
|
||||||
struct wl_shm *shm = term->wl->shm;
|
|
||||||
|
|
||||||
if (win->csd.move_timeout_fd != -1)
|
if (win->csd.move_timeout_fd != -1)
|
||||||
close(win->csd.move_timeout_fd);
|
close(win->csd.move_timeout_fd);
|
||||||
|
|
@ -1472,7 +1470,7 @@ wayl_win_destroy(struct wl_window *win)
|
||||||
|
|
||||||
tll_foreach(win->urls, it) {
|
tll_foreach(win->urls, it) {
|
||||||
wayl_win_subsurface_destroy(&it->item.surf);
|
wayl_win_subsurface_destroy(&it->item.surf);
|
||||||
shm_purge(shm, shm_cookie_url(it->item.url));
|
shm_purge(term->render.chains.url);
|
||||||
tll_remove(win->urls, it);
|
tll_remove(win->urls, it);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1481,13 +1479,13 @@ wayl_win_destroy(struct wl_window *win)
|
||||||
wayl_win_subsurface_destroy(&win->scrollback_indicator);
|
wayl_win_subsurface_destroy(&win->scrollback_indicator);
|
||||||
wayl_win_subsurface_destroy(&win->render_timer);
|
wayl_win_subsurface_destroy(&win->render_timer);
|
||||||
|
|
||||||
shm_purge(shm, shm_cookie_search(term));
|
shm_purge(term->render.chains.search);
|
||||||
shm_purge(shm, shm_cookie_scrollback_indicator(term));
|
shm_purge(term->render.chains.scrollback_indicator);
|
||||||
shm_purge(shm, shm_cookie_render_timer(term));
|
shm_purge(term->render.chains.render_timer);
|
||||||
shm_purge(shm, shm_cookie_grid(term));
|
shm_purge(term->render.chains.grid);
|
||||||
|
|
||||||
for (size_t i = 0; i < ALEN(win->csd.surface); i++)
|
for (size_t i = 0; i < ALEN(win->csd.surface); i++)
|
||||||
shm_purge(shm, shm_cookie_csd(term, i));
|
shm_purge(term->render.chains.csd[i]);
|
||||||
|
|
||||||
#if defined(HAVE_XDG_ACTIVATION)
|
#if defined(HAVE_XDG_ACTIVATION)
|
||||||
if (win->xdg_activation_token != NULL)
|
if (win->xdg_activation_token != NULL)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue