Commit graph

5827 commits

Author SHA1 Message Date
Daniel Eklöf
df71d9c6de
Merge branch 'sixel-performance'
Closes #1385
2023-06-29 15:40:21 +02:00
Daniel Eklöf
5e9d68695c
sixel: add_ar_11(): manually unroll loop
This generates both smaller, and faster code
2023-06-29 15:40:00 +02:00
Daniel Eklöf
fc46087ce9
scripts: generate-alt-random: set P2=1 when emitting sixels
P2=1 means "empty sixels remain at their current color". This is
usually the case with modern sixel encoders.
2023-06-29 15:40:00 +02:00
Daniel Eklöf
75f9bed6b6
sixel: refactor: shorten very verbose switch case statements 2023-06-29 15:40:00 +02:00
Daniel Eklöf
3555e81fee
sixel: special case parsing of images with an aspect ratio of 1:1
Images with an aspect ratio of 1:1 are by far the most common (though
not the default).

It makes a lot of sense, performance wise, to special case
them.

Specifically, the sixel_add() function benefits greatly from this, as
it is the inner most, most heavily executed function when parsing a
sixel image.

sixel_add_many() also benefits, since allows us to drop a
multiplication. Since sixel_add_many() always called first (no other
call sites call sixel_add() directly), this has a noticeable effect on
performance.

Another thing that helps (though not as much), and not specifically
with AR 1:1 images, is special casing DECGRI a bit.

Up until now, it simply updated the current sixel parameter value. The
problem is that the default parameter value is 0. But, a value of 0
should be treated as 1. By adding a special ‘repeat_count’ variable to
the sixel struct, we can initialize it to ‘1’ when we see DECGRI, and
then simply overwrite it as the parameter value gets updated. This
allows us to drop an if..else when emitting the sixel.
2023-06-29 15:40:00 +02:00
Daniel Eklöf
a44a0b4ebe
Merge branch 'fractional-scaling' 2023-06-29 15:38:42 +02:00
Daniel Eklöf
ce31cc518a
wayland: surface_scale(): reset buffer scale when using fractional scaling
Since the first frame uses legacy scaling, the surface may have a
buffer scale > 1, which isn’t allowed.
2023-06-29 15:38:24 +02:00
Daniel Eklöf
c61247f317
wayland: surface_scale(): improve debug logging 2023-06-29 15:38:24 +02:00
Daniel Eklöf
8f74b1090a
wayland: use legacy scaling until fractional_scale::preferred_scale() has been called
This way, the initial frame is more likely to get scaled correctly;
foot will guess the initial (integer) scale from the available
monitors, and use that. By using legacy scaling, we force the
compositor to down-scale the image to the correct scale factor.

If we use the new fraction scaling method with an integer scaling
factor, the initial frame gets rendered way too big.
2023-06-29 15:38:24 +02:00
Daniel Eklöf
d71e588800
wayland: refactor: surface_scale(): pass wl_window pointer, instead of wayland global 2023-06-29 15:38:24 +02:00
Daniel Eklöf
c309c9f572
wayland: surface_scale(): assert surface width/height is a multiple of scale
When doing legacy scaling (non-fractional scaling), assert the
surface’s width and height are multiples of the (integer) scale.
2023-06-29 15:38:24 +02:00
Daniel Eklöf
8a4efb3427
wayland: warn when fractional scaling isn’t available 2023-06-29 15:38:24 +02:00
Daniel Eklöf
9db92bd942
feature: add a feature flag (for --version) for fractional scaling 2023-06-29 15:38:24 +02:00
Daniel Eklöf
27a92b1158
changelog: dpi-aware’s default value is now ‘no’ 2023-06-29 15:38:23 +02:00
Daniel Eklöf
64b6b5d2a7
config: dpi-aware: remove ‘auto’ value, and default to ‘no’
We now default to scaling fonts using the scaling factor, not monitor
DPI.

The ‘auto’ value for dpi-aware has been removed.

Documentation (man pages and README) have been updated to reflect the
new default.
2023-06-29 15:38:23 +02:00
Daniel Eklöf
32b8c5c9b6
changelog: mention the newly added support for fractional-scaling-v1 2023-06-29 15:38:23 +02:00
Daniel Eklöf
0bdb6580bd
wayland: update terminal when preferred scaling factor changes
When the window’s preferred scaling factor is changed (through the
fractional-scaling protocol), update the terminal; resize font, resize
sub-surfaces etc.
2023-06-29 15:38:23 +02:00
Daniel Eklöf
8ccabb7974
wayland: surface_scale(): implement fractional scaling
This is done by setting the surface’s viewport destination
2023-06-29 15:38:23 +02:00
Daniel Eklöf
36818459e5
wayland: initialize window scale to -1 2023-06-29 15:38:23 +02:00
Daniel Eklöf
e5989d81b9
wayland: instantiate+destroy viewport for pointer surface 2023-06-29 15:38:23 +02:00
Daniel Eklöf
5a60bbc119
wayland: refactor: add a buffer argument to wayl_*_scale() functions
This will be needed later, when using fractional scaling + viewporter
to scale.
2023-06-29 15:38:23 +02:00
Daniel Eklöf
434fd6aa1f
wayland: refactor: wayl_surface_scale(): pass wayl_surface pointer
Instead of passing a raw wl_surface pointer, pass a wayl_surface
pointer.

This is needed later, when using fractional scaling to scale the
surface (since then we need the surface’s viewport object).
2023-06-29 15:38:23 +02:00
Daniel Eklöf
ba46a039ac
wayland: refactor: wrap wl_surface pointers in a wayl_surface struct
And add a viewport object to accompany the surface (to be used when
scaling the surface).

Also rename the wl_surf_subsurf struct to wayl_sub_surface, and add a
wayl_surface object to it, rather than a plain wl_surface pointer (to
also get the viewport pointer).
2023-06-29 15:38:23 +02:00
Daniel Eklöf
c5d533ec71
wayland: add viewport object to sub-surface struct 2023-06-29 15:38:23 +02:00
Daniel Eklöf
0a5073f570
wayland: add wayl_surface_scale(), and wayl_win_scale()
These functions scale a surface+buffer.

For now, only using the legacy scaling
method (wl_surface_set_buffer_scale()).
2023-06-29 15:38:23 +02:00
Daniel Eklöf
4bd62b1005
render: maybe_resize(): convert local variable ‘scale’ to float 2023-06-29 15:38:23 +02:00
Daniel Eklöf
913ae94cf9
wayland: add wayl_fractional_scaling()
Returns true if fractional scaling is available.
2023-06-29 15:38:22 +02:00
Daniel Eklöf
29a14632d3
wayland: csd_reload_font(): ‘scale’ is now a float 2023-06-29 15:38:22 +02:00
Daniel Eklöf
424d045084
term: reload_fonts(): ‘scale’ is not a float 2023-06-29 15:38:22 +02:00
Daniel Eklöf
2bb7b28837
render: xcursor_update(): convert local ‘scale’ variable to float 2023-06-29 15:38:22 +02:00
Daniel Eklöf
d8f64d1047
render: urls(): round scaling factor 2023-06-29 15:38:22 +02:00
Daniel Eklöf
30c8d3e652
render: search_box(): round scaling factor 2023-06-29 15:38:22 +02:00
Daniel Eklöf
cf280e6655
render: render_timer(): round scaling factor 2023-06-29 15:38:22 +02:00
Daniel Eklöf
b656124791
render: csd_border: round scaled border width, instead of truncating 2023-06-29 15:38:22 +02:00
Daniel Eklöf
44743b5635
render: draw_unfocused_block(): round scale, instead of truncating 2023-06-29 15:38:22 +02:00
Daniel Eklöf
6e2a47287a
wayland: pointer.scale: convert to float 2023-06-29 15:38:22 +02:00
Daniel Eklöf
c1f374cc8d
term: convert ‘scale’ to a float 2023-06-29 15:38:22 +02:00
Daniel Eklöf
a9ecf1449e
wayland: plumbing for wp-fractional-scale
* Bind the wp-viewporter and wp-fractional-scale-manager globals.
* Create a viewport and fractional-scale when instantiating a window.
* Add fractional-scale listener (that does nothing at the moment).
* Destroy everything on teardown.
2023-06-29 15:38:22 +02:00
Daniel Eklöf
1e6204e1ac
meson: generate bindings for wp-fractional-scale + wp-viewport 2023-06-29 15:38:17 +02:00
Vladimir Bauer
1dddb63d9f correct csd section entry: hide-when-maximized 2023-06-27 17:00:31 +05:00
Daniel Eklöf
d63a00a649
config: unittest: explicitly call fcft_init() + fcft_fini()
This plugs a memory leak, caused by fontconfig functions being called
as part of the unit test implicitly allocating global objects.
2023-06-26 20:15:36 +02:00
Daniel Eklöf
2388015b10
sixel: assert upper pixel of last sixel maps to last image row, *or lower* 2023-06-24 07:31:08 +02:00
Daniel Eklöf
c15e75357a
sixel: ensure enough rows have been scrolled in, to fit the image
When emitting a sixel, we need to:

a) scroll terminal content to ensure the new image fits
b) position the text cursor

Recent changes in the cursor positioning logic meant we reduced the
number of linefeeds, to ensure 1) sixels could be printed to the
bottom row without scrolling the terminal contents, and 2) the cursor
was positioned on the last sixel row.

Except, we’re not actually positioning the cursor on the last sixel
row. We’re positioning it on the text row that maps to the *upper*
pixel of the last sixel.

In most cases, this _is_ the last row of the sixel. But for certain
combinations of font and image sizes, it may be higher up.

This patch fixes a regression, where the terminal contents weren’t
scrolled up enough for certain images, causing a crash when trying to
dirty a not-yet scrolled in row.

The fix is this:

* Always scroll by the number of rows occupied by the image, minus
  one. This ensures the image "fits".
* Adjust the cursor position, if necessary.
2023-06-24 07:31:08 +02:00
Daniel Eklöf
425cf894d4
sixel: resize(): handle no size change 2023-06-24 07:31:08 +02:00
Daniel Eklöf
5d576fccba
sixel: regression: linefeed count for chunked up sixel image
All image chunks but the last *should* scroll the screen content.
2023-06-24 07:31:08 +02:00
Daniel Eklöf
1eb90b2405
sixel: minor fixes after implementing support for non-1:1 aspect ratios
* Lazy initialize image height. This is necessary to prevent garbage
  from being rendered for "empty" sixels.
* Fix plotting of non-1:1 pixels
* Fix calculation of height in resize(), for non-1:1 aspect ratios
2023-06-24 07:31:08 +02:00
Daniel Eklöf
774570ec41
sixel: stop cropping images to the last non-transparent row 2023-06-24 07:31:08 +02:00
Daniel Eklöf
d6d143e2a6
sixel: respect sixel aspect ratio
That is, parse P1 when initializing a new sixel, and don’t ignore
pad/pad in the raster attributes command.

The default aspect ratio is 2:1, but most sixels will override it in
the raster attributes command (to 1:1).
2023-06-24 07:31:08 +02:00
Daniel Eklöf
66d9b8da60
sixel: fix cursor positioning logic
This adjusts the logic that positions the text cursor after emitting a
sixel, when sixel scrolling mode is *enabled*.

We’ve always mimicked XTerm’s behavior. However, XTerm recently
changed its behavior, to better match that of an VT382.

Now, the cursor is placed *on* the last row of the sixel, instead of
on a new row after the sixel.

This allows applications to print sixels to the bottom row of the
terminal, without causing the content to scroll.

Finally, there was a bug in the horizontal positioning of the cursor;
it was placed on the *first* column of the row, instead of on the
first column of the sixel.
2023-06-24 07:31:02 +02:00
Daniel Eklöf
8a3620bafa
term: scroll: only record scroll damage when viewport is at the bottom
We don’t need to record scroll damage if the viewport isn’t at the
bottom, since in this case, the renderer ignores the scroll damage
anyway.

This fixes a performance corner case, when the viewport is at the top
of the scrollback history.

When application scrolls the terminal contents, and the scrollback
history is full, and the viewport is at top of the history, then the
viewport needs to be moved (the scrollback history is a circular
buffer, and thus the top of the history “moves” when we’re scrolling
in new contents).

Moving the viewport typically results in another type of scroll
damage (DAMAGE_SCROLL_IN_VIEW, instead of the “normal” DAMAGE_SCROLL).

Thus, each application triggered scroll, will result in two scroll
damage records: one DAMAGE_SCROLL, and one
DAMAGE_SCROLL_IN_VIEW. These two are incompatible, meaning they can’t
be merged. What’s worse, it also means the DAMAGE_SCROLL records from
two application triggered scrolls cannot be merged (since there’s a
DAMAGE_SCROLL_IN_VIEW in between).

As a result, the renderer will not see one, or “a few” scroll damage
events, but a *ton*. _Each_ one typically a single line, or so. And
each one resulting in lots of traffic on the wayland socket, as we
create and destroy new buffer pools, when doing “shm scrolling”.

This eventually leads to the socket not being able to keep up, and the
socket is closed on us, forcing us to exit.

The fix is really simple: don’t record “normal” scroll damage when
scrolling, _unless_ the viewport is at the bottom (and thus “follows”
the application output).

As soon as the user scrolls up in the history, we’ll stop emitting
normal scroll damage records. This is just fine, since, as mentioned
above, the renderer ignores them when the viewport isn’t at the
bottom.

What if the viewport is moved back down again, before the next frame
has been rendered? Wont there be “missing” scroll damage records? No,
because moving the viewport results in scroll damage records by
itself.

Closes #1380
2023-06-23 20:38:03 +02:00