Commit graph

4565 commits

Author SHA1 Message Date
Daniel Eklöf
34de799f90
Merge branch 'refactor-shm-buffer-management' 2021-07-18 11:41:14 +02:00
Daniel Eklöf
6657146a20
shm: chain_free: BUG() if there are buffers remaining after purge
There may be buffers left, if their destruction has been
deferred. However, they should be on the 'deferred' list, not the
chain's buffer list.

If there are buffers left on the chain's list, that means someone
forgot to call shm_unref().
2021-07-17 19:14:42 +02:00
Daniel Eklöf
0751172b92
shm: get_buffer: purge mismatching buffers in first buffer iteration
There's no longer any need to defer purging of mismatching buffer
(i.e. buffers whose width/height doesn't match the requested ones) to
after the cache lookup loop.
2021-07-17 19:14:42 +02:00
Daniel Eklöf
53851e13ec
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.
2021-07-17 19:14:42 +02:00
Daniel Eklöf
4efb34927e
shm: remove deferred buffers from main list immediately
When unref:ing a "busy" buffer, destruction is (still) deferred to the
buffer release event.

However, we now move the buffer off the buffer list immediately, and
instead push it to a 'deferred' list. This prevents buffer re-use of
buffers scheduled for destruction.

It also means less buffers to iterate through when trying to find a
re-usable buffer in shm_get_buffer(), since we no longer have to wade
through a potentially long list of to-be-deleted buffers.
2021-07-17 19:14:42 +02:00
Daniel Eklöf
232fb20269
shm: replace 'locked' attribute with a ref-counter
The initial ref-count is either 1 or 0, depending on whether the
buffer is supposed to be released "immeidately" (meaning, as soon as
the compositor releases it).

Two new user facing functions have been added: shm_addref() and
shm_unref().

Our renderer now uses these two functions instead of manually setting
and clearing the 'locked' attribute.

shm_unref() will decrement the ref-counter, and destroy the buffer
when the counter reaches zero. Except if the buffer is currently
"busy" (compositor owned), in which case destruction is deferred to
the release event. The buffer is still removed from the list though.
2021-07-17 19:14:42 +02:00
Daniel Eklöf
69260dd960
shm: we may exit with busy buffers remaining (seen on KDE) 2021-07-17 19:14:41 +02:00
Daniel Eklöf
99ea47c97a
shm: move ‘size’ to the private buffer struct 2021-07-17 19:14:41 +02:00
Daniel Eklöf
f5da62c462
shm: replace inclusion of terminal.h with a forward declaration of damage
It’s the only thing we “need” from terminal.h
2021-07-17 19:14:41 +02:00
Daniel Eklöf
9b6cee825b
shm: rename buffer.mmapped to buffer.data 2021-07-17 19:14:41 +02:00
Daniel Eklöf
75f7f21a48
shm: split up buffer struct into internal/private and public parts 2021-07-17 19:14:41 +02:00
Daniel Eklöf
a18959f2df
Merge branch 'allow-bleeding-glyphs' 2021-07-17 19:14:00 +02:00
Timur Celik
91801ae55d render: Allow cells to bleed into their neighbor
This patch adds a `confined` flag to each cell to track if the last
rendered glyph bled into it's right neighbor.  To keep things simple,
bleeding into any other neighbor cell than the immediate right one is
not allowed.  This should cover most use cases.

Before rendering a row we now do a prepass and mark all cells unclean
that are affected by a bleeding neighbor.  If there are consecutive
bleeding cells, the whole group must be re-rendered even if only a
single cell has changed.

The patch also deprecates both old overflowing glyph options
*allow-overflowing-double-width-glyphs* and *pua-double-width* in favor
of a single new one named *overflowing-glyphs*.
2021-07-17 13:22:44 +02:00
Daniel Eklöf
9211ee694c
Merge branch 'decsdm'
Closes #631
2021-07-16 17:33:30 +02:00
Daniel Eklöf
931595bda5
shm: codespell 2021-07-15 19:40:15 +02:00
Daniel Eklöf
a486851bdd
shm: auto-purge when we have multiple buffers eligible for re-use
It may happen that we end up with multiple non-busy, same-sized
buffers for the same cookie (context), and thus eligible for re-use.

Before this patch, we would keep all those buffers around. This is
completely unnecessary. Under normal circumstances, we’ll either be
re-using a single buffer, or swap between two. In the second case, the
“other” buffer is always busy, and thus not eligible for re-use.

So, if we _do_ detect multiple, re-usable buffers, pick the one with
the lowest “age” (increasing the chance of applying damage tracking,
instead of re-drawing everything), and mark the other one for purging.
2021-07-15 19:19:31 +02:00
Daniel Eklöf
5d7b729ac5
wayland: win_destroy: unmap URL labels 2021-07-15 18:45:25 +02:00
Daniel Eklöf
31fad58465
url-mode: use shm_get_many()
If we have lots of URLs, we use up a *lot* of SHM buffers (and thus
pools). Each and every one is a single mmap(), of at least 4K.

Since all URL labels are created and destroyed at the same time, it
makes sense to use a single pool for all buffers.

To do this, we must now do two passes; first one to generate the
actual string (label content), and to calculate the label sizes.

Then we use this information to allocate all SHM buffers at once, from
the same pool.

Finally, we iterate the URLs again, this time to actually render them.
2021-07-15 18:39:41 +02:00
Daniel Eklöf
7533684d8f
shm: add shm_get_many() - allows buffers to share a single pool
shm_get_many() always returns new buffers (i.e. never old, cached
ones). The newly allocated buffers are also marked for immediate
purging, meaning they’ll be destroyed on the next call to either
shm_get_buffer(), or shm_get_many().

Furthermore, we add a new attribute, ‘locked’, to the buffer
struct. When auto purging buffers, look at this instead of comparing
cookies.

Buffer consumers are expected to set ‘locked’ while they hold a
reference to it, and don’t want it destroyed behind their back.
2021-07-15 18:39:23 +02:00
Daniel Eklöf
5e64c67c25
render: search: set clip region
Fixes crash when the search box has been reduced in height, due to
limited window space.
2021-07-15 18:27:10 +02:00
Daniel Eklöf
628fd39098
render: scrollback indicator: improve handling of very small window sizes 2021-07-15 18:26:26 +02:00
Daniel Eklöf
e259f460f3
render: margins: use correct background color
* Sync actual color used, with how render_cell() selects the
  background color
* Use color_dim_for_search(), not color_dim()
2021-07-15 18:24:27 +02:00
Daniel Eklöf
fcc2e62a7d
render: track alpha directly, rather whether to use it or not 2021-07-15 18:23:49 +02:00
Daniel Eklöf
22651ed221
shm: reset buffer pool FD when we close it
This fixes an issue where we ended up "double closing" buffer FDs.

In many cases (especially on compositors with SSDs) this was pretty
rare. And even when it did happen, the FD was normally unused, and
thus nothing bad happened.

However, by quickly resizing the window while using CSDs, it was
fairly easy to trigger this. We sometimes ended up closing the
TIOCSWINCH timer FD while thinking it was a buffer FD, but most of the
times we just ended up closing _another_ buffer’s pool FD, leading to
an immediate disconnect by the compositor.
2021-07-14 20:51:42 +02:00
Daniel Eklöf
9658e9cc18
render: tiocswinsz: don’t remove/close the fd passed as argument
There’s a chance the resize timeout FD was closed, and *reused*, after
epoll() told us the FD is readable, but before our callback runs.

Thus, closing the FD provided as an argument is dangerous, as it may
refer to something completely different.
2021-07-14 20:14:10 +02:00
Daniel Eklöf
0c777d825d
Revert "render: don’t assume PIXMAN_a8r8g8b8 for color glyphs"
This reverts commit 9b4796e996.

Sub-pixel anti-aliasing also uses 32-bit glyphs (but x8r8g8b8, instead
of a8r8g8b8)...
2021-07-14 19:56:11 +02:00
Daniel Eklöf
654e65631d
changelog: box-drawing fixes on big-endian 2021-07-14 19:48:13 +02:00
Daniel Eklöf
34f42b3dd6
box-drawing: big-endian support when setting bits manually 2021-07-14 19:46:21 +02:00
Daniel Eklöf
9b4796e996
render: don’t assume PIXMAN_a8r8g8b8 for color glyphs
We may want to use PIXMAN_b8g8r8a8 on big-endian in the future.
2021-07-14 19:46:18 +02:00
Daniel Eklöf
fcd9897342
csi: invert the meaning of DECSDM
There has been some confusion whether enabling DECSDM (private mode
80) enables or disables sixel scrolling.

Foot currently enables scrolling when DECSDM is set, and this patch
changes this, such that setting DECSDM now *disables* scrolling.

The confusion is apparently due to a documentation error in the VT340
manual, as described in
https://github.com/dankamongmen/notcurses/issues/1782#issuecomment-863603641.

And that makes sense, in a way: the SDM in DECSDM stands for Sixel
Display Mode. I.e. it stands to reason that enabling that disables
scrolling.

Anyway, this lead to https://github.com/hackerb9/lsix/issues/41, where
it was eventually proven (by testing on a real VT340), that foot, and
a large number of other terminals (including XTerm) has it wrong:
https://github.com/hackerb9/lsix/issues/41#issuecomment-873269599.
2021-07-14 19:17:44 +02:00
Daniel Eklöf
7afc4c8037
Merge branch 'crash-on-runaway-url' 2021-07-11 13:19:40 +02:00
Daniel Eklöf
8290cebc09
server: the terminal now purges SHM pixmaps on its own 2021-07-11 11:54:08 +02:00
Daniel Eklöf
f030c87ee6
url-mode: abort when running into un-allocated scrollback memory
When tagging URL cells (in preparation for rendering URL mode), we
loop the URL’s entire range, setting the `url` attribute of all cells,
and dirtying the rows.

It is possible to create URLs that are invalid, and wrap around the
scrollback, even though the scrollback hasn’t yet been filled. For
example, by starting an OSC-8 URL, moving the cursor, and then closing
the OSC-8 URL.

These URLs are invalid, but are still rendered just fine. “Fine” being
relative - they will typically fill the entire screen. But at least
that’s a very clear indication for the user that’s something is wrong.

The problem is when we hit un-allocated scrollback rows. We didn’t
check for NULL rows, and crashed.

This has now been fixed.
2021-07-11 11:31:11 +02:00
Daniel Eklöf
d22ba73c41
Merge branch 'crash-in-url-mode-remove-duplicates'
Closes #627
2021-07-11 11:30:31 +02:00
Daniel Eklöf
107cbb1015
shm: close pool FD if buffer doesn’t support SHM scrolling
The only reason to keep the pool FD open is if we’re going to SHM
scroll the buffer; we need the FD for fallocate(FALLOC_FL_PUNCH_HOLE).

In all other cases, there’s absolutely no need to keep the FD
open. Thus, close it as soon as we’ve instantiated the buffer. This
frees up FDs, and help keep foot from FD ulimit.
2021-07-11 10:22:47 +02:00
Daniel Eklöf
cf6d04f9f2
url-mode: fix crash when removing duplicate and/or overlapping URLs
Removing overlaping and duplicated URLs is done by running two nested
loops, that both iterate the same URL list.

When a duplicate is found, one of the URLs is destroyed and removed
from the list.

Deleting and removing an item *is* safe, but only as long as _no
other_ iterator has references to it.

In this case, if we remove an item from e.g. the inner iterator, we’ll
crash if the outer iterator’s *next* item is the item being removed.

Closes #627
2021-07-11 10:06:12 +02:00
Daniel Eklöf
a9872aac5a
wayland: explicitly purge all SHM pixmaps when destroying window
All SHM pixmap cookies depend on the terminal instance’s memory
address. Thus, after a terminal instance has been destroyed, shm
pixmaps that belonged to it will never be purged automatically.
2021-07-11 10:01:22 +02:00
Daniel Eklöf
b5950d9b27
wayland: purge CSD pixmaps when destroying the CSDs
CSDs aren’t typically toggled on and off. Thus, when disabled,
immediately purge their corresponding pixmap buffers, to free up some
memory, and release file descriptors.
2021-07-11 09:59:25 +02:00
Daniel Eklöf
0a6e7e6167
url-mode: purge SHM pixmaps when destroying URLs
Unlike other surface types, the SHM cookie depends on the address of
each URL instance. This means if we enable, disable, and then enable
URL mode again (thus showing exactly the same URLs as the first time),
the URLs will have new addresses, and thus the old SHM pixmaps will
not get purged automatically.

So, manually purge them when destroying the URLs.
2021-07-11 09:59:17 +02:00
Daniel Eklöf
24dd44634a
Merge branch 'man-page-typo' 2021-07-08 20:04:56 +02:00
Ben Brown
9a14e5d818 doc: fix typo in foot man page 2021-07-08 10:43:51 +01:00
Daniel Eklöf
6f1f1f5614
Merge branch 'locked-title' 2021-07-07 19:51:40 +02:00
Daniel Eklöf
fcb60abc13
config: add locked-title=no|yes
Closes #386
2021-07-04 17:59:40 +02:00
Daniel Eklöf
07652d3b9e
term: rows printed to now defaults to having a hard linebreak
That is, instead of requiring a ‘\n’ to be printed, non-empty lines
are now treated as having a hard linebreak by default.

The linebreak is cleared on an explicit wrap.
2021-07-03 18:05:45 +02:00
Daniel Eklöf
d101325885
doc: foot.ini.5: typo: relay-size-ms -> resize-delay-ms 2021-07-02 16:53:49 +02:00
Daniel Eklöf
85b63b5e4a
render: require glyph count > 0 and cell-cols also for forced double-width PUAs 2021-07-02 16:48:46 +02:00
Daniel Eklöf
396a5ff79b
allow-overflowing-double-width-glyphs: take glyph offset into account
A narrow, but offset:ed glyph should still be considered double
width.

This patch also fixes a crash, when the maybe-double width glyph is in
the last column. This is a regression.
2021-07-02 16:31:14 +02:00
Craig Barnes
562096a21a foot.ini: mention Control+c in default "cancel" key bindings
This should have been done as part of commit
6eb6668c3c.
2021-07-02 09:12:57 +01:00
Craig Barnes
b18d3aef17 vt: add some unit tests for action_collect() 2021-07-02 08:46:28 +01:00
Daniel Eklöf
4e8db9d8b6
changelog: s/from/in 2021-07-01 20:44:53 +02:00