From 774a6e7f8c525ab501a5fd43070664398a07c110 Mon Sep 17 00:00:00 2001 From: Miles Breslin Date: Sat, 16 Jan 2021 14:22:26 -0800 Subject: [PATCH 1/7] Basic damage tracking --- Makefile | 2 +- dwl.c | 22 +++++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index a0d1cc3..81bf017 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ CFLAGS += -I. -DWLR_USE_UNSTABLE -std=c99 WAYLAND_PROTOCOLS=$(shell pkg-config --variable=pkgdatadir wayland-protocols) WAYLAND_SCANNER=$(shell pkg-config --variable=wayland_scanner wayland-scanner) -PKGS = wlroots wayland-server xcb xkbcommon libinput +PKGS = wlroots wayland-server xcb xkbcommon libinput pixman-1 CFLAGS += $(foreach p,$(PKGS),$(shell pkg-config --cflags $(p))) LDLIBS += $(foreach p,$(PKGS),$(shell pkg-config --libs $(p))) diff --git a/dwl.c b/dwl.c index 4098f86..9f2367c 100644 --- a/dwl.c +++ b/dwl.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -176,6 +177,7 @@ struct Monitor { double mfact; int nmaster; Client *fullscreenclient; + struct wlr_output_damage *damage; }; typedef struct { @@ -779,6 +781,10 @@ commitnotify(struct wl_listener *listener, void *data) /* mark a pending resize as completed */ if (c->resize && c->resize <= c->surface.xdg->configure_serial) c->resize = 0; + + // Damage the whole screen + if (c->mon) + wlr_output_damage_add_whole(c->mon->damage); } void @@ -823,6 +829,7 @@ createmon(struct wl_listener *listener, void *data) /* Initialize monitor state using configured rules */ for (size_t i = 0; i < LENGTH(m->layers); i++) wl_list_init(&m->layers[i]); + m->damage = wlr_output_damage_create(wlr_output); m->tagset[0] = m->tagset[1] = 1; for (r = monrules; r < END(monrules); r++) { if (!r->name || strstr(wlr_output->name, r->name)) { @@ -1760,7 +1767,14 @@ rendermon(struct wl_listener *listener, void *data) if (!wlr_output_attach_render(m->wlr_output, NULL)) return; - if (render) { + bool needs_frame; + pixman_region32_t damage; + pixman_region32_init(&damage); + if (!wlr_output_damage_attach_render(m->damage, &needs_frame, &damage)) { + BARF("Cannot make damage output current"); + } + + if (render && needs_frame) { /* Begin the renderer (calls glViewport and some other GL sanity checks) */ wlr_renderer_begin(drw, m->wlr_output->width, m->wlr_output->height); wlr_renderer_clear(drw, rootcolor); @@ -1785,8 +1799,14 @@ rendermon(struct wl_listener *listener, void *data) /* Conclude rendering and swap the buffers, showing the final frame * on-screen. */ wlr_renderer_end(drw); + + wlr_output_set_damage(m->wlr_output, &m->damage->current); + } else { + wlr_output_rollback(m->wlr_output); } + pixman_region32_fini(&damage); + wlr_output_commit(m->wlr_output); } From 98f1c3f3d8244c14803efbaa7306883c65422e8b Mon Sep 17 00:00:00 2001 From: Miles Breslin Date: Sat, 16 Jan 2021 21:35:03 -0800 Subject: [PATCH 2/7] Damage the screen for new and removed clients as well --- dwl.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/dwl.c b/dwl.c index 9f2367c..4ce5826 100644 --- a/dwl.c +++ b/dwl.c @@ -147,6 +147,7 @@ typedef struct { struct wlr_box geo; enum zwlr_layer_shell_v1_layer layer; + Monitor *mon; } LayerSurface; typedef struct { @@ -771,6 +772,10 @@ commitlayersurfacenotify(struct wl_listener *listener, void *data) &layersurface->link); layersurface->layer = wlr_layer_surface->current.layer; } + + // Damage the whole screen + if (selmon) + wlr_output_damage_add_whole(selmon->damage); } void @@ -1020,6 +1025,11 @@ destroynotify(struct wl_listener *listener, void *data) { /* Called when the surface is destroyed and should never be shown again. */ Client *c = wl_container_of(listener, c, destroy); + + // Damage the whole screen + if (c->mon) + wlr_output_damage_add_whole(c->mon->damage); + wl_list_remove(&c->map.link); wl_list_remove(&c->unmap.link); wl_list_remove(&c->destroy.link); @@ -1362,6 +1372,10 @@ mapnotify(struct wl_listener *listener, void *data) /* Set initial monitor, tags, floating status, and focus */ applyrules(c); + + // Damage the whole screen + wlr_output_damage_add_whole(c->mon->damage); + if (c->mon->fullscreenclient && c->mon->fullscreenclient == oldfocus && !c->isfloating && c->mon->lt[c->mon->sellt]->arrange) { maximizeclient(c->mon->fullscreenclient); @@ -1964,6 +1978,7 @@ setmon(Client *c, Monitor *m, unsigned int newtags) if (oldmon) { wlr_surface_send_leave(client_surface(c), oldmon->wlr_output); arrange(oldmon); + wlr_output_damage_add_whole(oldmon->damage); } if (m) { /* Make sure window actually overlaps with the monitor */ @@ -1971,6 +1986,7 @@ setmon(Client *c, Monitor *m, unsigned int newtags) wlr_surface_send_enter(client_surface(c), m->wlr_output); c->tags = newtags ? newtags : m->tagset[m->seltags]; /* assign tags of target monitor */ arrange(m); + wlr_output_damage_add_whole(m->damage); } focusclient(focustop(selmon), 1); } @@ -2289,6 +2305,11 @@ unmapnotify(struct wl_listener *listener, void *data) { /* Called when the surface is unmapped, and should no longer be shown. */ Client *c = wl_container_of(listener, c, unmap); + + // Damage the whole screen + if (c->mon) + wlr_output_damage_add_whole(c->mon->damage); + wl_list_remove(&c->link); if (client_is_unmanaged(c)) return; From 1e3a66478dad98f302654eefb6507044ddd65248 Mon Sep 17 00:00:00 2001 From: Miles Breslin Date: Mon, 18 Jan 2021 15:19:45 -0800 Subject: [PATCH 3/7] Damage Tracking: Reduce unnecessary code --- dwl.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/dwl.c b/dwl.c index 4ce5826..722da7d 100644 --- a/dwl.c +++ b/dwl.c @@ -774,8 +774,7 @@ commitlayersurfacenotify(struct wl_listener *listener, void *data) } // Damage the whole screen - if (selmon) - wlr_output_damage_add_whole(selmon->damage); + wlr_output_damage_add_whole(m->damage); } void @@ -1372,7 +1371,6 @@ mapnotify(struct wl_listener *listener, void *data) /* Set initial monitor, tags, floating status, and focus */ applyrules(c); - // Damage the whole screen wlr_output_damage_add_whole(c->mon->damage); @@ -1777,16 +1775,11 @@ rendermon(struct wl_listener *listener, void *data) } } - /* wlr_output_attach_render makes the OpenGL context current. */ - if (!wlr_output_attach_render(m->wlr_output, NULL)) - return; - bool needs_frame; pixman_region32_t damage; pixman_region32_init(&damage); - if (!wlr_output_damage_attach_render(m->damage, &needs_frame, &damage)) { - BARF("Cannot make damage output current"); - } + if (!wlr_output_damage_attach_render(m->damage, &needs_frame, &damage)) + return; if (render && needs_frame) { /* Begin the renderer (calls glViewport and some other GL sanity checks) */ From e17445bb43726c8bf35f1e1a384dd98d51f3834d Mon Sep 17 00:00:00 2001 From: Miles Breslin Date: Mon, 18 Jan 2021 16:01:20 -0800 Subject: [PATCH 4/7] Simpler damage implementation --- Makefile | 2 +- dwl.c | 43 +++++++++++++++---------------------------- 2 files changed, 16 insertions(+), 29 deletions(-) diff --git a/Makefile b/Makefile index 81bf017..a0d1cc3 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ CFLAGS += -I. -DWLR_USE_UNSTABLE -std=c99 WAYLAND_PROTOCOLS=$(shell pkg-config --variable=pkgdatadir wayland-protocols) WAYLAND_SCANNER=$(shell pkg-config --variable=wayland_scanner wayland-scanner) -PKGS = wlroots wayland-server xcb xkbcommon libinput pixman-1 +PKGS = wlroots wayland-server xcb xkbcommon libinput CFLAGS += $(foreach p,$(PKGS),$(shell pkg-config --cflags $(p))) LDLIBS += $(foreach p,$(PKGS),$(shell pkg-config --libs $(p))) diff --git a/dwl.c b/dwl.c index 722da7d..e3e8516 100644 --- a/dwl.c +++ b/dwl.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -147,7 +146,6 @@ typedef struct { struct wlr_box geo; enum zwlr_layer_shell_v1_layer layer; - Monitor *mon; } LayerSurface; typedef struct { @@ -178,7 +176,7 @@ struct Monitor { double mfact; int nmaster; Client *fullscreenclient; - struct wlr_output_damage *damage; + int isdamaged; }; typedef struct { @@ -773,8 +771,7 @@ commitlayersurfacenotify(struct wl_listener *listener, void *data) layersurface->layer = wlr_layer_surface->current.layer; } - // Damage the whole screen - wlr_output_damage_add_whole(m->damage); + m->isdamaged = true; } void @@ -786,9 +783,8 @@ commitnotify(struct wl_listener *listener, void *data) if (c->resize && c->resize <= c->surface.xdg->configure_serial) c->resize = 0; - // Damage the whole screen if (c->mon) - wlr_output_damage_add_whole(c->mon->damage); + c->mon->isdamaged = true; } void @@ -833,7 +829,7 @@ createmon(struct wl_listener *listener, void *data) /* Initialize monitor state using configured rules */ for (size_t i = 0; i < LENGTH(m->layers); i++) wl_list_init(&m->layers[i]); - m->damage = wlr_output_damage_create(wlr_output); + m->isdamaged = 1; m->tagset[0] = m->tagset[1] = 1; for (r = monrules; r < END(monrules); r++) { if (!r->name || strstr(wlr_output->name, r->name)) { @@ -1025,9 +1021,8 @@ destroynotify(struct wl_listener *listener, void *data) /* Called when the surface is destroyed and should never be shown again. */ Client *c = wl_container_of(listener, c, destroy); - // Damage the whole screen if (c->mon) - wlr_output_damage_add_whole(c->mon->damage); + c->mon->isdamaged = true; wl_list_remove(&c->map.link); wl_list_remove(&c->unmap.link); @@ -1371,8 +1366,7 @@ mapnotify(struct wl_listener *listener, void *data) /* Set initial monitor, tags, floating status, and focus */ applyrules(c); - // Damage the whole screen - wlr_output_damage_add_whole(c->mon->damage); + c->mon->isdamaged = true; if (c->mon->fullscreenclient && c->mon->fullscreenclient == oldfocus && !c->isfloating && c->mon->lt[c->mon->sellt]->arrange) { @@ -1775,13 +1769,14 @@ rendermon(struct wl_listener *listener, void *data) } } - bool needs_frame; - pixman_region32_t damage; - pixman_region32_init(&damage); - if (!wlr_output_damage_attach_render(m->damage, &needs_frame, &damage)) + /* wlr_output_attach_render makes the OpenGL context current. */ + if (!wlr_output_attach_render(m->wlr_output, NULL)) return; - if (render && needs_frame) { + // We must render the monitor twice, once for each buffer, each time damage occurs + if (render && (m->isdamaged > -1)) { + m->isdamaged--; + /* Begin the renderer (calls glViewport and some other GL sanity checks) */ wlr_renderer_begin(drw, m->wlr_output->width, m->wlr_output->height); wlr_renderer_clear(drw, rootcolor); @@ -1806,14 +1801,8 @@ rendermon(struct wl_listener *listener, void *data) /* Conclude rendering and swap the buffers, showing the final frame * on-screen. */ wlr_renderer_end(drw); - - wlr_output_set_damage(m->wlr_output, &m->damage->current); - } else { - wlr_output_rollback(m->wlr_output); } - pixman_region32_fini(&damage); - wlr_output_commit(m->wlr_output); } @@ -1971,7 +1960,7 @@ setmon(Client *c, Monitor *m, unsigned int newtags) if (oldmon) { wlr_surface_send_leave(client_surface(c), oldmon->wlr_output); arrange(oldmon); - wlr_output_damage_add_whole(oldmon->damage); + oldmon->isdamaged = true; } if (m) { /* Make sure window actually overlaps with the monitor */ @@ -1979,7 +1968,7 @@ setmon(Client *c, Monitor *m, unsigned int newtags) wlr_surface_send_enter(client_surface(c), m->wlr_output); c->tags = newtags ? newtags : m->tagset[m->seltags]; /* assign tags of target monitor */ arrange(m); - wlr_output_damage_add_whole(m->damage); + m->isdamaged = true; } focusclient(focustop(selmon), 1); } @@ -2299,9 +2288,7 @@ unmapnotify(struct wl_listener *listener, void *data) /* Called when the surface is unmapped, and should no longer be shown. */ Client *c = wl_container_of(listener, c, unmap); - // Damage the whole screen - if (c->mon) - wlr_output_damage_add_whole(c->mon->damage); + c->mon->isdamaged = true; wl_list_remove(&c->link); if (client_is_unmanaged(c)) From 5f260a3d36708327a59dd4c8dff649ae9911f262 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Tue, 19 Jan 2021 00:41:14 -0600 Subject: [PATCH 5/7] Revert "Simpler damage implementation" This reverts commit 59b05a9cd81f124aaf726d00c0b00e8465486018. It was worth seeing how well this would work. --- Makefile | 2 +- dwl.c | 43 ++++++++++++++++++++++++++++--------------- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/Makefile b/Makefile index a0d1cc3..81bf017 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ CFLAGS += -I. -DWLR_USE_UNSTABLE -std=c99 WAYLAND_PROTOCOLS=$(shell pkg-config --variable=pkgdatadir wayland-protocols) WAYLAND_SCANNER=$(shell pkg-config --variable=wayland_scanner wayland-scanner) -PKGS = wlroots wayland-server xcb xkbcommon libinput +PKGS = wlroots wayland-server xcb xkbcommon libinput pixman-1 CFLAGS += $(foreach p,$(PKGS),$(shell pkg-config --cflags $(p))) LDLIBS += $(foreach p,$(PKGS),$(shell pkg-config --libs $(p))) diff --git a/dwl.c b/dwl.c index e3e8516..722da7d 100644 --- a/dwl.c +++ b/dwl.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -146,6 +147,7 @@ typedef struct { struct wlr_box geo; enum zwlr_layer_shell_v1_layer layer; + Monitor *mon; } LayerSurface; typedef struct { @@ -176,7 +178,7 @@ struct Monitor { double mfact; int nmaster; Client *fullscreenclient; - int isdamaged; + struct wlr_output_damage *damage; }; typedef struct { @@ -771,7 +773,8 @@ commitlayersurfacenotify(struct wl_listener *listener, void *data) layersurface->layer = wlr_layer_surface->current.layer; } - m->isdamaged = true; + // Damage the whole screen + wlr_output_damage_add_whole(m->damage); } void @@ -783,8 +786,9 @@ commitnotify(struct wl_listener *listener, void *data) if (c->resize && c->resize <= c->surface.xdg->configure_serial) c->resize = 0; + // Damage the whole screen if (c->mon) - c->mon->isdamaged = true; + wlr_output_damage_add_whole(c->mon->damage); } void @@ -829,7 +833,7 @@ createmon(struct wl_listener *listener, void *data) /* Initialize monitor state using configured rules */ for (size_t i = 0; i < LENGTH(m->layers); i++) wl_list_init(&m->layers[i]); - m->isdamaged = 1; + m->damage = wlr_output_damage_create(wlr_output); m->tagset[0] = m->tagset[1] = 1; for (r = monrules; r < END(monrules); r++) { if (!r->name || strstr(wlr_output->name, r->name)) { @@ -1021,8 +1025,9 @@ destroynotify(struct wl_listener *listener, void *data) /* Called when the surface is destroyed and should never be shown again. */ Client *c = wl_container_of(listener, c, destroy); + // Damage the whole screen if (c->mon) - c->mon->isdamaged = true; + wlr_output_damage_add_whole(c->mon->damage); wl_list_remove(&c->map.link); wl_list_remove(&c->unmap.link); @@ -1366,7 +1371,8 @@ mapnotify(struct wl_listener *listener, void *data) /* Set initial monitor, tags, floating status, and focus */ applyrules(c); - c->mon->isdamaged = true; + // Damage the whole screen + wlr_output_damage_add_whole(c->mon->damage); if (c->mon->fullscreenclient && c->mon->fullscreenclient == oldfocus && !c->isfloating && c->mon->lt[c->mon->sellt]->arrange) { @@ -1769,14 +1775,13 @@ rendermon(struct wl_listener *listener, void *data) } } - /* wlr_output_attach_render makes the OpenGL context current. */ - if (!wlr_output_attach_render(m->wlr_output, NULL)) + bool needs_frame; + pixman_region32_t damage; + pixman_region32_init(&damage); + if (!wlr_output_damage_attach_render(m->damage, &needs_frame, &damage)) return; - // We must render the monitor twice, once for each buffer, each time damage occurs - if (render && (m->isdamaged > -1)) { - m->isdamaged--; - + if (render && needs_frame) { /* Begin the renderer (calls glViewport and some other GL sanity checks) */ wlr_renderer_begin(drw, m->wlr_output->width, m->wlr_output->height); wlr_renderer_clear(drw, rootcolor); @@ -1801,8 +1806,14 @@ rendermon(struct wl_listener *listener, void *data) /* Conclude rendering and swap the buffers, showing the final frame * on-screen. */ wlr_renderer_end(drw); + + wlr_output_set_damage(m->wlr_output, &m->damage->current); + } else { + wlr_output_rollback(m->wlr_output); } + pixman_region32_fini(&damage); + wlr_output_commit(m->wlr_output); } @@ -1960,7 +1971,7 @@ setmon(Client *c, Monitor *m, unsigned int newtags) if (oldmon) { wlr_surface_send_leave(client_surface(c), oldmon->wlr_output); arrange(oldmon); - oldmon->isdamaged = true; + wlr_output_damage_add_whole(oldmon->damage); } if (m) { /* Make sure window actually overlaps with the monitor */ @@ -1968,7 +1979,7 @@ setmon(Client *c, Monitor *m, unsigned int newtags) wlr_surface_send_enter(client_surface(c), m->wlr_output); c->tags = newtags ? newtags : m->tagset[m->seltags]; /* assign tags of target monitor */ arrange(m); - m->isdamaged = true; + wlr_output_damage_add_whole(m->damage); } focusclient(focustop(selmon), 1); } @@ -2288,7 +2299,9 @@ unmapnotify(struct wl_listener *listener, void *data) /* Called when the surface is unmapped, and should no longer be shown. */ Client *c = wl_container_of(listener, c, unmap); - c->mon->isdamaged = true; + // Damage the whole screen + if (c->mon) + wlr_output_damage_add_whole(c->mon->damage); wl_list_remove(&c->link); if (client_is_unmanaged(c)) From 38fe38478386e65b747a1c074458650fc86435fe Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Tue, 19 Jan 2021 01:29:28 -0600 Subject: [PATCH 6/7] stick to dwm style --- dwl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dwl.c b/dwl.c index 722da7d..eed7b18 100644 --- a/dwl.c +++ b/dwl.c @@ -1759,6 +1759,8 @@ rendermon(struct wl_listener *listener, void *data) { Client *c; int render = 1; + bool needs_frame; + pixman_region32_t damage; /* This function is called every time an output is ready to display a frame, * generally at the output's refresh rate (e.g. 60Hz). */ @@ -1775,8 +1777,6 @@ rendermon(struct wl_listener *listener, void *data) } } - bool needs_frame; - pixman_region32_t damage; pixman_region32_init(&damage); if (!wlr_output_damage_attach_render(m->damage, &needs_frame, &damage)) return; From 8616d947b789c24e5a05b69ab9bb063b3fe95930 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Tue, 19 Jan 2021 02:17:57 -0600 Subject: [PATCH 7/7] make rendermon more straightforward Prior to damage tracking, we had to make sure wlr_output_commit was called even if we weren't rendering anything new. If we didn't, then nothing would render after attempting the first window resize. This is no longer a problem (maybe because adding damage schedules another frame callback?), so we can do some normal early-returns here. --- dwl.c | 70 +++++++++++++++++++++++++++++------------------------------ 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/dwl.c b/dwl.c index eed7b18..e8ad714 100644 --- a/dwl.c +++ b/dwl.c @@ -1758,7 +1758,7 @@ void rendermon(struct wl_listener *listener, void *data) { Client *c; - int render = 1; + int render; bool needs_frame; pixman_region32_t damage; @@ -1769,51 +1769,51 @@ rendermon(struct wl_listener *listener, void *data) struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - /* Do not render if any XDG clients have an outstanding resize. */ + /* If there is any XDG client which is awaiting resize, request a new + * frame from that client, and do not render anything new until there + * are no pending resizes remaining. */ wl_list_for_each(c, &stack, slink) { if (c->resize) { wlr_surface_send_frame_done(client_surface(c), &now); - render = 0; + return; } } + /* Do not render if no new frame is needed */ pixman_region32_init(&damage); - if (!wlr_output_damage_attach_render(m->damage, &needs_frame, &damage)) - return; - - if (render && needs_frame) { - /* Begin the renderer (calls glViewport and some other GL sanity checks) */ - wlr_renderer_begin(drw, m->wlr_output->width, m->wlr_output->height); - wlr_renderer_clear(drw, rootcolor); - - renderlayer(&m->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &now); - renderlayer(&m->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &now); - renderclients(m, &now); -#ifdef XWAYLAND - renderindependents(m->wlr_output, &now); -#endif - renderlayer(&m->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &now); - renderlayer(&m->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &now); - - /* Hardware cursors are rendered by the GPU on a separate plane, and can be - * moved around without re-rendering what's beneath them - which is more - * efficient. However, not all hardware supports hardware cursors. For this - * reason, wlroots provides a software fallback, which we ask it to render - * here. wlr_cursor handles configuring hardware vs software cursors for you, - * and this function is a no-op when hardware cursors are in use. */ - wlr_output_render_software_cursors(m->wlr_output, NULL); - - /* Conclude rendering and swap the buffers, showing the final frame - * on-screen. */ - wlr_renderer_end(drw); - - wlr_output_set_damage(m->wlr_output, &m->damage->current); - } else { + render = wlr_output_damage_attach_render(m->damage, &needs_frame, &damage); + pixman_region32_fini(&damage); + if (!render || !needs_frame) { + /* Rollback is needed because attach_render is double-buffered */ wlr_output_rollback(m->wlr_output); + return; } - pixman_region32_fini(&damage); + /* Begin the renderer (calls glViewport and some other GL sanity checks) */ + wlr_renderer_begin(drw, m->wlr_output->width, m->wlr_output->height); + wlr_renderer_clear(drw, rootcolor); + renderlayer(&m->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &now); + renderlayer(&m->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &now); + renderclients(m, &now); +#ifdef XWAYLAND + renderindependents(m->wlr_output, &now); +#endif + renderlayer(&m->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &now); + renderlayer(&m->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &now); + + /* Hardware cursors are rendered by the GPU on a separate plane, and can be + * moved around without re-rendering what's beneath them - which is more + * efficient. However, not all hardware supports hardware cursors. For this + * reason, wlroots provides a software fallback, which we ask it to render + * here. wlr_cursor handles configuring hardware vs software cursors for you, + * and this function is a no-op when hardware cursors are in use. */ + wlr_output_render_software_cursors(m->wlr_output, NULL); + + /* Conclude rendering and swap the buffers, showing the final frame + * on-screen. */ + wlr_renderer_end(drw); + wlr_output_set_damage(m->wlr_output, &m->damage->current); wlr_output_commit(m->wlr_output); }