Commit graph

30 commits

Author SHA1 Message Date
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
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
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
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
34becf0df0
render: code cleanup, log double buffering time
* Break out cursor cell dirtying to separate functions
* Break out handling of double buffering
* Handle buffers with age > 1 (we’re swapping between more than 2
  buffers)
* Detect full screen repaints, and skip re-applying old frame’s damage
* Use an allocated array insted of a tll list for old frame’s scroll damage
* When logging frame rendering time, including the amount used for
  double buffering.
2021-05-12 20:06:15 +02:00
Daniel Eklöf
434c9c3a34
shm: add damage tracking to buffer 2021-05-12 20:06:15 +02:00
Daniel Eklöf
c8b342ae51
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).
2021-05-12 20:06:04 +02:00
Daniel Eklöf
2cc84db979
urls: initial support for detecting URLs and rendering jump-labels
The jump labels work, but is currently hardcoded to use xdg-open
2021-02-07 16:33:31 +01:00
Daniel Eklöf
17070a0d54
config: add tweak.render-timer option
This can be set to 'none' (the default), 'osd', 'log' or 'both'.

When 'osd' is enabled, we'll render the frame rendering time to a
sub-surface after each frame.

When 'log' is enabled, the frame rendering time is logged on stderr.
2020-08-13 18:35:17 +02:00
Daniel Eklöf
a39c490d9b
shm: add shm_cookie_scrollback_indicator() 2020-07-26 10:00:21 +02:00
Daniel Eklöf
8b320ed296
render: re-write cell clipping to use pixman destination clipping
Our home rolled clip-to-cell code was, obviously, not correct.

The original problem was that we couldn't use pixman clipping since we
have multiple threads writing to the same pixman image, and thus there
would be races between the threads setting clipping.

The fix is actually simple - just instantiate one pixman
image (referencing the same backing image data) for each rendering
thread.
2020-06-04 15:39:19 +02:00
Daniel Eklöf
0baa249d8b
shm: make max pool size user configurable (via a 'tweak' setting) 2020-03-25 20:48:02 +01:00
Daniel Eklöf
03319560f5
shm: scroll: keep shm pool around, and fix its size at max allowed
This lessens the burden on (primarily) the compositor, since we no
longer tear down and re-create the SHM pool when scrolling.

The SHM pool is setup once, and its size is fixed at the maximum
allowed (512MB for now, 2GB would be possible).

This also allows us to mmap() the memfd once. The exposed raw pointer
is simply an offset from the memfd mmapping.

Note that this means e.g. rouge rendering code will be able to write
outside the buffer.

Finally, only do this if the caller explicitly wants to enable
scrolling. The memfd of other buffers are sized to the requested size.
2020-03-25 18:26:58 +01:00
Daniel Eklöf
5c5f1d096c
shm: scroll: implement offset wrap-around
* Impose a maximum memfd size limit. In theory, this can be
  2GB (wl_shm_create_pool() is the limiting factor - its size argument
  is an int32_t). For now, use 256MB.

  This is mainly to reduce the amount of virtual address space used by
  the compositor, which keeps at least one mmapping (of the entire
  memfd) around. One mmapping *per terminal window* that is.

  Given that we have 128TB with 48-bit virtual addresses, we could
  probably bump this to 2GB without any issues. However, 256MB should
  be enough.

  TODO: check how much we typically move the offset when scrolling in
  a fullscreen window on a 4K monitor. 256MB may turn out to be too
  small.

  On 32-bit shm_scroll() is completely disabled. There simply isn't
  enough address space.

* Wrapping is done by moving the offset to "the other end" of the
  memfd, and copying the buffer contents to the new, wrapped offset.

  The "normal" scrolling code then does the actual scrolling. This
  means we'll re-instantiate all objects twice when wrapping.
2020-03-24 17:46:48 +01:00
Daniel Eklöf
0de3701984
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.
2020-03-23 20:45:27 +01:00
Daniel Eklöf
5ffee08748
shm: add shm_can_scroll() 2020-03-23 19:31:05 +01:00
Daniel Eklöf
1224807f50
shm: new function, shm_scroll()
This function "scrolls" the buffer by the specified number of (pixel)
rows.

The idea is move the image offset by re-sizing the underlying memfd
object. I.e. to scroll forward, increase the size of the memfd file,
and move the pixman image offset forward (and the Wayland SHM buffer
as well).

Only increasing the file size would, obviously, cause the memfd file
to grow indefinitely. To deal with this, we "punch" a whole from the
beginning of the file to the new offset. This frees the associated
memory.

Thus, while we have a memfd file whose size is (as seen by
e.g. fstat()) is ever growing, the actual file size is always the
original buffer size.

Some notes:

* FALLOC_FL_PUNCH_HOLE can be quite slow when the number of used pages
  to drop is large.

* all normal fallocate() usages have been replaced with ftruncate(),
  as this is *much* faster. fallocate() guarantees subsequent writes
  wont fail. I.e. it actually reserves (disk) space. While it doesn't
  allocate on-disk blocks for on-disk files, it *does* zero-initialize
  the in-memory blocks. And this is slow. ftruncate() doesn't do this.

TODO: implement reverse scrolling (i.e. a negative row count).
2020-03-22 20:06:44 +01:00
Daniel Eklöf
6a35abb6ca
shm: new functions: shm_cookie_*()
These functions return a SHM cookie given a terminal instance.
2020-03-18 16:52:33 +01:00
Daniel Eklöf
c6c75298f3
shm: automatic buffer purging is now delayed one cycle
This ensures we don't purge a buffer that a user is holding a
reference to.
2019-11-02 01:27:05 +01:00
Daniel Eklöf
8e5d386afc
shm: add shm_purge()
Destroys *all* buffers associated with the specified cookie.
2019-11-02 00:49:00 +01:00
Daniel Eklöf
00b46455a0
shm: associate a 'cookie' with each buffer
When re-using a buffer from cache, only re-use ones with a matching
cookie.

This prevents contention between multiple terminal windows.
2019-11-02 00:33:37 +01:00
Daniel Eklöf
8df82938b0
shm: get_buffer(): remove 'copies' argument; it's not used 2019-11-02 00:23:51 +01:00
Daniel Eklöf
72d3cbca26
shm/render: there's no need to have one pixman image per thread 2019-08-16 22:54:05 +02:00
Daniel Eklöf
f45e5c6aef
Remove all references to cairo; we now use pixman only 2019-08-16 22:11:22 +02:00
Daniel Eklöf
bed7b34c28
wip: render background and glyphs using pixman 2019-08-16 20:40:32 +02:00
Daniel Eklöf
c531795b83
wip: initial multithreaded renderer 2019-07-29 20:13:26 +02:00
Daniel Eklöf
910c540ea9
initial commit: maps an XDG toplevel window 2019-06-12 20:08:54 +02:00