Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use wlroots scene graph api #6844

Merged
merged 28 commits into from
Jan 18, 2024
Merged

Use wlroots scene graph api #6844

merged 28 commits into from
Jan 18, 2024

Conversation

Nefsen402
Copy link
Member

@Nefsen402 Nefsen402 commented Feb 21, 2022

Closes: #6562 #7120 #6914 #6821 #6960 #6148 #5867 #5497 #5460 #6469 #7458 #7463
Supersedes: #6820 #6747

This should be enough where if most people were on this patch, they wouldn't know it. However, there are some features still missing from the port:

  • Opacity support
    Scene graph doesn't have support for specifying the opacity of a wlr_scene_surface.
    However, implementing this would not be enough because we send in xdg surfaces
    into relevant helper functions that hide the surfaces / subsurfaces away from us. The easiest
    fix from the perspective of the user is the ability to specify the opacity of an entire subtree.
  • Surface scissor
    We're also missing support for specifying a scissor region for a surface node. This is useful
    because it will prevent applications that don't respect a configure from possibly rendering
    on top of other tiled applications. Again, the actual surface nodes are hidden from us, so it
    would be easiest to specify a scissor region for an entire subtree.
  • Buffer node output awareness
    Scenes already handle client output awareness for us (wlr_surface_send_enter, wlr_surface_send_leave)
    However, we don't have this information for buffer nodes so we can do more optimized
    text rending. For now text rendering is hard coded to a 2x screen scale and grey scale sub
    pixel handling. An appropriate solution to this problem is to support wl_signals for
    output enter/exit events and the ability to overwrite the buffer in a wlr_scene_buffer.
  • scale_filter option
    Scenes do linear filtering only. We need some way to specify this.
  • Upstream issue for gamma correction during direct scanout: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3609

Wayland backend specific bugs (not regressions of this branch):

  • Xwayland damage tracking issues, especially noticeable when entering/exiting full screen.
    This seems like a wlroots bug.
  • Xwayland cropped cursor on HiDPI
    This is probably a bug I introduced but I'm not sure. This also happens sometimes in
    sway-git, maybe I messed the code up enough to make it 100% reproducible.
  • Pointer lock doesn't work

Although there are xwayland damage tracking issues, this does not mean that current git is unaffected
by damage tracking issues. In fact, this branch fixes damage tracking issues with subsurfaces on a
xdg_surface popup, so as far as I know, for wayland clients damage tracking is perfect.

@Nefsen402 Nefsen402 changed the title Use wlroots sceen graph api Use wlroots scene graph api Feb 21, 2022
@Nefsen402
Copy link
Member Author

Hmm, the xwayland damage tracking issue goes away on DRM. That's very strange.

@Nefsen402 Nefsen402 force-pushed the scene-graph branch 2 times, most recently from 5a4daf3 to 914982a Compare February 22, 2022 00:11
@Nefsen402
Copy link
Member Author

Xwayland cropped cursor also goes away on DRM.

@Nefsen402 Nefsen402 force-pushed the scene-graph branch 5 times, most recently from de21489 to 8d7349c Compare February 22, 2022 04:01
@Nefsen402
Copy link
Member Author

Nefsen402 commented Feb 22, 2022

I'm getting some sort of nonsense SIGSEGV crash on DRM. This is what was in the core dump. @emersion can you make anything out in this?

[Current thread is 1 (Thread 0x7ffff671f5c0 (LWP 74245))]
(gdb) bt full
#0  0x00007ffff78603e0 in  () at /usr/lib/libxkbcommon.so.0
#1  0x00007ffff792e0c0 in wlr_keyboard_keymaps_match (km1=0x55555632a080, km2=0x300000002) at ../types/wlr_keyboard.c:284
        km1_str = 0x55555624cf80 "xkb_keymap {\nxkb_keycodes \"(unnamed)\" {\n\tminimum = 8;\n\tmaximum = 708;\n\t<ESC>", ' ' <repeats 16 times>, "= 9;\n\t<AE01>", ' ' <repeats 15 times>, "= 10;\n\t<AE02>", ' ' <repeats 15 times>, "= 11;\n\t<AE03>", ' ' <repeats 15 times>, "= 12;\n\t<AE04>", ' ' <repeats 12 times>...
        km2_str = 0x555555f842e0 "\320\313\001VUU"
        result = false
#2  0x0000555555584589 in sway_keyboard_group_remove_invalid (keyboard=0x555556329320) at ../sway/input/keyboard.c:872
        group = 0x5555562b6e10
        device = 0x55555631c2f0
        wlr_keyboard = 0x555556329150
        seat = 0x555555ea5e70
        sc = 0x555555f842e0
#3  0x0000555555584f24 in sway_keyboard_configure (keyboard=0x555556329320) at ../sway/input/keyboard.c:1082
        input_config = 0x0
        wlr_device = 0x5555563290d0
        __PRETTY_FUNCTION__ = "sway_keyboard_configure"
        keymap = 0x5555569828c0
        keymap_changed = false
        effective_layout_changed = false
        repeat_rate = 25
        repeat_delay = 600
        repeat_info_changed = false
        seat = 0x55555631c2f0
#4  0x0000555555588320 in seat_configure_keyboard (seat=0x555555ea5e70, seat_device=0x55555631c1e0) at ../sway/input/seat.c:781
        focus = 0x555555585a87 <sway_input_configure_libinput_device+24>
#5  0x000055555558865f in seat_configure_device (seat=0x555555ea5e70, input_device=0x55555631c2f0) at ../sway/input/seat.c:858
        seat_device = 0x55555631c1e0
#6  0x000055555557e093 in input_manager_configure_input (input_device=0x55555631c2f0) at ../sway/input/input-manager.c:530
        seat = 0x555555ea5e70
#7  0x000055555557e0f8 in input_manager_configure_all_inputs () at ../sway/input/input-manager.c:537
        input_device = 0x55555631c2f0
#8  0x00005555555c26e8 in output_disable (output=0x55555634ec10) at ../sway/tree/output.c:282
        __PRETTY_FUNCTION__ = "output_disable"
        index = 0
#9  0x000055555557817b in handle_destroy (listener=0x55555634ed08, data=0x55555634e030) at ../sway/desktop/output.c:212
        output = 0x55555634ec10
        server = 0x5555555e85c0 <server>
--Type <RET> for more, q to quit, c to continue without paging--
#10 0x00007ffff794e2a4 in wlr_signal_emit_safe (signal=0x55555634e250, data=0x55555634e030) at ../util/signal.c:29
        pos = 0x55555634ed08
        l = 0x55555634ed08
        cursor = {link = {prev = 0x55555634ed08, next = 0x555556326040}, notify = 0x7ffff794e1ee <handle_noop>}
        end = {link = {prev = 0x55555699c128, next = 0x55555634e250}, notify = 0x7ffff794e1ee <handle_noop>}
#11 0x00007ffff790873b in wlr_output_destroy (output=0x55555634e030) at ../types/output/output.c:429
        cursor = 0x55555560b840
        tmp_cursor = 0x7ffff79a8000
#12 0x00007ffff78e8809 in disconnect_drm_connector (conn=0x55555634e030) at ../backend/drm/drm.c:1540
        __PRETTY_FUNCTION__ = "disconnect_drm_connector"
#13 0x00007ffff78e885a in destroy_drm_connector (conn=0x55555634e030) at ../backend/drm/drm.c:1546
#14 0x00007ffff78e279f in backend_destroy (backend=0x555555622c30) at ../backend/drm/backend.c:38
        drm = 0x555555622c30
        conn = 0x55555634e030
        next = 0x55555634e3a0
        fb = 0x555556017ee8
        fb_tmp = 0x5555563290d0
#15 0x00007ffff78e0be9 in wlr_backend_destroy (backend=0x555555622c30) at ../backend/backend.c:63
#16 0x00007ffff78f61a4 in multi_backend_destroy (wlr_backend=0x55555560b7f0) at ../backend/multi/backend.c:59
        sub = 0x5555556160b0
        backend = 0x55555560b7f0
#17 0x00007ffff78f63b5 in handle_display_destroy (listener=0x55555560b840, data=0x55555560b700) at ../backend/multi/backend.c:134
        backend = 0x55555560b7f0
#18 0x00007ffff79b28ff in wl_display_destroy () at /usr/lib/libwayland-server.so.0
#19 0x0000555555575460 in server_fini (server=0x5555555e85c0 <server>) at ../sway/server.c:263
#20 0x00005555555748fd in main (argc=1, argv=0x7fffffffead8) at ../sway/main.c:436
        verbose = false
        debug = false
        validate = false
        allow_unsupported_gpu = false
        long_options = 
            {{name = 0x5555555cb230 "help", has_arg = 0, flag = 0x0, val = 104}, {name = 0x5555555cb235 "config", has_arg = 1, flag = 0x0, val = 99}, {name = 0x5555555cb23c "validate", has_arg = 0, flag = 0x0, val = 67}, {name = 0x5555555cb245 "debug", has_arg = 0, flag = 0x0, val = 100}, {name = 0x5555555cb24b "version", has_arg = 0, flag = 0x0, val = 118}, {name = 0x5555555cb253 "verbose", has_arg = 0, flag = 0x0, val = 86}, {name = 0x5555555cb25b "get-socketpath", has_arg = 0, flag = 0x0, val = 112}, {name = 0x5555555cb26a "unsupported-gpu", has_arg = 0, flag = 0x0, val = 117}, {name = 0x0, has_arg = 0, flag = 0x0, val = 0}}
        config_path = 0x0
        usage = 0x5555555cac88 "Usage: sway [options] [command]\n\n  -h, --help", ' ' <repeats 13 times>, "Show help message and quit.\n  -c, --co--Type <RET> for more, q to quit, c to continue without paging--
nfig <config>  Specify a config file.\n  -C, --validate         Check the validity of the config file, th"...
        c = -1

@Nefsen402 Nefsen402 force-pushed the scene-graph branch 2 times, most recently from ba6f116 to b4456b0 Compare February 22, 2022 05:50
@Nefsen402
Copy link
Member Author

Nefsen402 commented Feb 22, 2022

I have another code dump here that makes more sense. 0x1900000000 is a fishy address for wlr_keyboard->group

Program terminated with signal SIGSEGV, Segmentation fault.

warning: Section `.reg-xstate/88561' in core file too small.
#0  0x0000557470b9f596 in sway_keyboard_group_remove_invalid (keyboard=0x557472977a70) at ../sway/input/keyboard.c:872
--Type <RET> for more, q to quit, c to continue without paging--
872			if (!wlr_keyboard_keymaps_match(keyboard->keymap, group->keyboard.keymap) ||
[Current thread is 1 (Thread 0x7fe4060b35c0 (LWP 88561))]
(gdb) bt full
#0  0x0000557470b9f596 in sway_keyboard_group_remove_invalid (keyboard=0x557472977a70) at ../sway/input/keyboard.c:872
        group = 0x1900000000
        device = 0x55747296aa40
        wlr_keyboard = 0x5574729778a0
        seat = 0x5574724efcb0
        sc = 0x5574725cd100
#1  0x0000557470b9ff4b in sway_keyboard_configure (keyboard=0x557472977a70) at ../sway/input/keyboard.c:1082
        input_config = 0x0
        wlr_device = 0x557472977820
        __PRETTY_FUNCTION__ = "sway_keyboard_configure"
        keymap = 0x55747257c980
        keymap_changed = false
        effective_layout_changed = false
        repeat_rate = 25
        repeat_delay = 600
        repeat_info_changed = false
        seat = 0x55747296aa40
#2  0x0000557470ba3347 in seat_configure_keyboard (seat=0x5574724efcb0, seat_device=0x55747296a930) at ../sway/input/seat.c:781
        focus = 0x557470ba0aae <sway_input_configure_libinput_device+24>
#3  0x0000557470ba3686 in seat_configure_device (seat=0x5574724efcb0, input_device=0x55747296aa40) at ../sway/input/seat.c:858
        seat_device = 0x55747296a930
#4  0x0000557470b990ba in input_manager_configure_input (input_device=0x55747296aa40) at ../sway/input/input-manager.c:530
        seat = 0x5574724efcb0
#5  0x0000557470b9911f in input_manager_configure_all_inputs () at ../sway/input/input-manager.c:537
        input_device = 0x55747296aa40
#6  0x0000557470bdd70f in output_disable (output=0x557472990a70) at ../sway/tree/output.c:281
        __PRETTY_FUNCTION__ = "output_disable"
        index = 0
#7  0x0000557470b9317b in handle_destroy (listener=0x557472990b68, data=0x5574729b0b60) at ../sway/desktop/output.c:211
        output = 0x557472990a70
        server = 0x557470c035c0 <server>
#8  0x00007fe4072e22a4 in wlr_signal_emit_safe (signal=0x5574729b0d80, data=0x5574729b0b60) at ../util/signal.c:29
        pos = 0x557472990b68
        l = 0x557472990b68
        cursor = {link = {prev = 0x557472990b68, next = 0x5574729b06b0}, notify = 0x7fe4072e21ee <handle_noop>}
        end = {link = {prev = 0x557472fe9b18, next = 0x5574729b0d80}, notify = 0x7fe4072e21ee <handle_noop>}
#9  0x00007fe40729c73b in wlr_output_destroy (output=0x5574729b0b60) at ../types/output/output.c:429
        cursor = 0x557471c55840
        tmp_cursor = 0x7fe40733c000
#10 0x00007fe40727c809 in disconnect_drm_connector (conn=0x5574729b0b60) at ../backend/drm/drm.c:1540
        __PRETTY_FUNCTION__ = "disconnect_drm_connector"
#11 0x00007fe40727c85a in destroy_drm_connector (conn=0x5574729b0b60) at ../backend/drm/drm.c:1546
#12 0x00007fe40727679f in backend_destroy (backend=0x557471c6cc30) at ../backend/drm/backend.c:38
        drm = 0x557471c6cc30
        conn = 0x5574729b0b60
        next = 0x5574729b0ed0
        fb = 0x557472660c38
        fb_tmp = 0x557472977820
#13 0x00007fe407274be9 in wlr_backend_destroy (backend=0x557471c6cc30) at ../backend/backend.c:63
#14 0x00007fe40728a1a4 in multi_backend_destroy (wlr_backend=0x557471c557f0) at ../backend/multi/backend.c:59
        sub = 0x557471c600b0
        backend = 0x557471c557f0
#15 0x00007fe40728a3b5 in handle_display_destroy (listener=0x557471c55840, data=0x557471c55700) at ../backend/multi/backend.c:134
        backend = 0x557471c557f0
#16 0x00007fe4073468ff in wl_display_destroy () at /usr/lib/libwayland-server.so.0
#17 0x0000557470b90460 in server_fini (server=0x557470c035c0 <server>) at ../sway/server.c:263
#18 0x0000557470b8f8fd in main (argc=1, argv=0x7ffd6dd386a8) at ../sway/main.c:436

@Nefsen402 Nefsen402 force-pushed the scene-graph branch 3 times, most recently from 875e534 to a4bc9f8 Compare February 24, 2022 01:08
include/sway/scene_descriptor.h Outdated Show resolved Hide resolved
include/sway/sway_buffer.h Outdated Show resolved Hide resolved
@Nefsen402 Nefsen402 force-pushed the scene-graph branch 5 times, most recently from 6a92bba to 1efda98 Compare February 27, 2022 09:32
@Xyene
Copy link
Member

Xyene commented Feb 27, 2022

Thanks for working on this!

I've patched my local install with this PR, and will dogfood it for a while.

Some early notes (I'll update this list as I come across things):

  • Some transactions seem delayed, despite not being logged as having timed out. If I have a workspace with only V[kitty kitty] and try interactive resizing, it is very juddery. V[uxterm uxterm] works fine, as do some other apps.
  • Borders are sometimes drawn in the wrong location, seems to be most easily triggered with kitty and very uneven splits. The borders are persistent (i.e. are not damage artifacts). If I had to guess, they are the borders from hidden tabs, the last time they were visible? They go away when flicking between tabs. Visual example:
Left kitty panel has borders drawn in the wrong place

image

@Nefsen402
Copy link
Member Author

  • Borders are sometimes drawn in the wrong location

Seems to be a regression of a recent memory leak fix, I changed out the layout of the tree structure and I forgot to disable non-visible borders.

  • Some transactions seem delayed

Thanks for letting me know about this oddball application. I'm able to reproduce. None of my applications have transaction issues so I haven't noticed there's a problem.

@Xyene
Copy link
Member

Xyene commented Feb 27, 2022

  • Presentation time seems to be unimplemented or nonfunctional.
  • When floating a tabbed application, the tab bar remained visible but wasn't redrawn to the right dimensions. Not all applications seem to trigger this.
Screenshot

image

  • Other tab orientations that shouldn't be possible:
Screenshot

image

  • Rearranging layouts via window drag-and-drop (while holding Ctrl) appears nonfunctional. Rearranging tabs works, though.

  • Gaps drawn in unexpected places:

Screenshot

image

@Nefsen402 Nefsen402 force-pushed the scene-graph branch 2 times, most recently from ade88c1 to 7afd6b8 Compare February 27, 2022 23:40
Nefsen402 and others added 14 commits January 18, 2024 10:04
Instead of doing this roundabout thing where we get the surface from the
view, let's instead get it from the `wlr_surface_state` that we already
track in `handle_commit`. This makes the NULL state impossible which is
what the old `get_geometry` is checking for and generally cleans
things up a little bit.

Also don't check if the geometry x/y changed, those will always
be 0 for xwayland.
The new scene graph abstraction handles this for us.
The scene graph abstraction does this for us
```
Program terminated with signal SIGSEGV, Segmentation fault.

warning: Section `.reg-xstate/3960717' in core file too small.
0  container_get_siblings (container=0x55bcde4797f0) at ../sway/tree/container.c:1228
1228		if (list_find(container->pending.workspace->tiling, container) != -1) {
[Current thread is 1 (Thread 0x7fa23b4a2940 (LWP 3960717))]
(gdb) bt full=
No symbol "full" in current context.
(gdb) bt full
0  container_get_siblings (container=0x55bcde4797f0) at ../sway/tree/container.c:1228
1  0x000055bcdb62c704 in edge_is_external (cont=0x55bcde4797f0, edge=(WLR_EDGE_TOP | WLR_EDGE_LEFT))
    at ../sway/input/seatop_default.c:54
        siblings = 0x55bcde4797f0
        index = 32766
        layout = L_NONE
        __PRETTY_FUNCTION__ = "edge_is_external"
2  0x000055bcdb62c96f in find_resize_edge (cont=0x55bcde4797f0, surface=0x0, cursor=0x55bcddd5c2e0)
    at ../sway/input/seatop_default.c:106
        edge = (WLR_EDGE_TOP | WLR_EDGE_LEFT)
3  0x000055bcdb620b3c in cursor_update_image (cursor=0x55bcddd5c2e0, node=0x55bcde4797f0) at ../sway/input/cursor.c:144
        edge = WLR_EDGE_NONE
4  0x000055bcdb62eb8f in handle_rebase (seat=0x55bcddd5a740, time_msec=488992944) at ../sway/input/seatop_default.c:773
        e = 0x55bcddd5c8e0
        cursor = 0x55bcddd5c2e0
        surface = 0x0
        sx = 0
        sy = 0
5  0x000055bcdb62c531 in seatop_rebase (seat=0x55bcddd5a740, time_msec=488992944) at ../sway/input/seat.c:1585
6  0x000055bcdb620a7d in cursor_rebase (cursor=0x55bcddd5c2e0) at ../sway/input/cursor.c:126
        time_msec = 488992944
7  0x000055bcdb620ac4 in cursor_rebase_all () at ../sway/input/cursor.c:136
        seat = 0x55bcddd5a740
8  0x000055bcdb61cc95 in transaction_apply (transaction=0x55bcde5b28c0) at ../sway/desktop/transaction.c:704
9  0x000055bcdb61ccdb in transaction_progress () at ../sway/desktop/transaction.c:716
10 0x000055bcdb61d1f9 in transaction_commit_pending () at ../sway/desktop/transaction.c:836
        transaction = 0x55bcde5b28c0
11 0x000055bcdb61d596 in _transaction_commit_dirty (server_request=true) at ../sway/desktop/transaction.c:912
12 0x000055bcdb61d5ac in transaction_commit_dirty () at ../sway/desktop/transaction.c:916
13 0x000055bcdb65f579 in view_unmap (view=0x55bcde2ff180) at ../sway/tree/view.c:847
        parent = 0x55bcde489010
        ws = 0x55bcdde19080
        seat = 0x55bcddd5a198
14 0x000055bcdb61e461 in handle_unmap (listener=0x55bcde2ff368, data=0x0) at ../sway/desktop/xdg_shell.c:394
        xdg_shell_view = 0x55bcde2ff180
        view = 0x55bcde2ff180
        __PRETTY_FUNCTION__ = "handle_unmap"
15 0x00007fa23c4ae87f in wlr_signal_emit_safe (signal=0x55bcde46cf38, data=0x0) at ../util/signal.c:29
        pos = 0x55bcde2ff368
        l = 0x55bcde2ff368
        cursor = {link = {prev = 0x55bcde2ff368, next = 0x7ffe240702a0}, notify = 0x7fa23c4ae7c9 <handle_noop>}
        end = {link = {prev = 0x7ffe24070280, next = 0x55bcde46cf38}, notify = 0x7fa23c4ae7c9 <handle_noop>}
16 0x00007fa23c47c3c7 in unmap_xdg_surface (surface=0x55bcde46ce30) at ../types/xdg_shell/wlr_xdg_surface.c:40
        __PRETTY_FUNCTION__ = "unmap_xdg_surface"
        popup = 0x55bcde46ce60
        popup_tmp = 0x55bcde46ce60
        configure = 0x7ffe24070360
        tmp = 0x55bcde488020
17 0x00007fa23c47cd47 in xdg_surface_role_precommit (wlr_surface=0x55bcde488020, state=0x55bcde4881a8)
    at ../types/xdg_shell/wlr_xdg_surface.c:330
        surface = 0x55bcde46ce30
18 0x00007fa23c4813b2 in surface_commit_state (surface=0x55bcde488020, next=0x55bcde4881a8) at ../types/wlr_compositor.c:407
        __PRETTY_FUNCTION__ = "surface_commit_state"
        invalid_buffer = false
        subsurface = 0xbd8e9aecae023300
--Type <RET> for more, q to quit, c to continue without paging--
19 0x00007fa23c48192a in surface_handle_commit (client=0x55bcde488850, resource=0x55bcde2fdb80) at ../types/wlr_compositor.c:523
        surface = 0x55bcde488020
20 0x00007fa23bb5ed4a in  () at /usr/lib/libffi.so.8
21 0x00007fa23bb5e267 in  () at /usr/lib/libffi.so.8
22 0x00007fa23c517323 in  () at /usr/lib/libwayland-server.so.0
23 0x00007fa23c5125cc in  () at /usr/lib/libwayland-server.so.0
24 0x00007fa23c5151ca in wl_event_loop_dispatch () at /usr/lib/libwayland-server.so.0
25 0x00007fa23c512d37 in wl_display_run () at /usr/lib/libwayland-server.so.0
26 0x000055bcdb616885 in server_run (server=0x55bcdb68c5c0 <server>) at ../sway/server.c:307
27 0x000055bcdb61594e in main (argc=3, argv=0x7ffe24070af8) at ../sway/main.c:433
```

It seems to be happening because of this set of events all happening
in the span of a single transaction:
1. You kill a tiled window that is the only window in a workplace.
2. Sway will destroy the workspace but not yet the container - this
   makes `con->pending.workspace` NULL.
3. Cursor glyphs get recomputed causing sway to recompute if the cursor
   is on a container edge. 
4. That computation causes an access to the NULL workspace. Crash.
Now that we use wlr_scene, wlroots handles these. If available use
the wlroots debug options instead.
Copy link
Member

@vyivel vyivel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@iambumblehead
Copy link

@Nefsen402 you are appreciated :) thank you! can't wait to use this!

emersion pushed a commit that referenced this pull request Jan 26, 2024
Since output layout is destroyed when the wayland display is destroyed
we run into a destroy listener order problem: Either the display starts
destroying the outputs first, in which case we're good: The existing
handling will clean up. However, things go wrong if the display decides
to destroy the output layout first. In this case, sway will hold
invalid references to the output layout as part of each output so that
when it finally goes to destroy them, sway will dereference destroyed
output layout bits.

Ref: #6844 (comment)
(cherry picked from commit bbabb9a)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Use wlroots' scene-graph API Damage artifacts with fractional scaling