aboutsummaryrefslogtreecommitdiffstats
path: root/sway
diff options
context:
space:
mode:
authorLibravatar Simon Ser <contact@emersion.fr>2024-03-14 13:54:08 +0100
committerLibravatar Kenny Levinsen <kl@kl.wtf>2024-03-14 22:55:46 +0100
commit3bc75221bc0074b2e96e14cb88140c95406472c3 (patch)
treef8f63fb9a2192c0953fe787c9d018dc03d090ad6 /sway
parentserver: fix wlr_seat use-after-free on exit (diff)
downloadsway-3bc75221bc0074b2e96e14cb88140c95406472c3.tar.gz
sway-3bc75221bc0074b2e96e14cb88140c95406472c3.tar.zst
sway-3bc75221bc0074b2e96e14cb88140c95406472c3.zip
Re-create renderer when lost
Diffstat (limited to 'sway')
-rw-r--r--sway/server.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/sway/server.c b/sway/server.c
index 94d0fae2..51bde794 100644
--- a/sway/server.c
+++ b/sway/server.c
@@ -172,6 +172,45 @@ static void detect_proprietary(struct wlr_backend *backend, void *data) {
172 drmFreeVersion(version); 172 drmFreeVersion(version);
173} 173}
174 174
175static void handle_renderer_lost(struct wl_listener *listener, void *data) {
176 struct sway_server *server = wl_container_of(listener, server, renderer_lost);
177
178 sway_log(SWAY_INFO, "Re-creating renderer after GPU reset");
179
180 struct wlr_renderer *renderer = wlr_renderer_autocreate(server->backend);
181 if (renderer == NULL) {
182 sway_log(SWAY_ERROR, "Unable to create renderer");
183 return;
184 }
185
186 struct wlr_allocator *allocator =
187 wlr_allocator_autocreate(server->backend, renderer);
188 if (allocator == NULL) {
189 sway_log(SWAY_ERROR, "Unable to create allocator");
190 wlr_renderer_destroy(renderer);
191 return;
192 }
193
194 struct wlr_renderer *old_renderer = server->renderer;
195 struct wlr_allocator *old_allocator = server->allocator;
196 server->renderer = renderer;
197 server->allocator = allocator;
198
199 wl_list_remove(&server->renderer_lost.link);
200 wl_signal_add(&server->renderer->events.lost, &server->renderer_lost);
201
202 wlr_compositor_set_renderer(server->compositor, renderer);
203
204 for (int i = 0; i < root->outputs->length; ++i) {
205 struct sway_output *output = root->outputs->items[i];
206 wlr_output_init_render(output->wlr_output,
207 server->allocator, server->renderer);
208 }
209
210 wlr_allocator_destroy(old_allocator);
211 wlr_renderer_destroy(old_renderer);
212}
213
175bool server_init(struct sway_server *server) { 214bool server_init(struct sway_server *server) {
176 sway_log(SWAY_DEBUG, "Initializing Wayland server"); 215 sway_log(SWAY_DEBUG, "Initializing Wayland server");
177 server->wl_display = wl_display_create(); 216 server->wl_display = wl_display_create();
@@ -195,6 +234,9 @@ bool server_init(struct sway_server *server) {
195 return false; 234 return false;
196 } 235 }
197 236
237 server->renderer_lost.notify = handle_renderer_lost;
238 wl_signal_add(&server->renderer->events.lost, &server->renderer_lost);
239
198 wlr_renderer_init_wl_shm(server->renderer, server->wl_display); 240 wlr_renderer_init_wl_shm(server->renderer, server->wl_display);
199 241
200 if (wlr_renderer_get_dmabuf_texture_formats(server->renderer) != NULL) { 242 if (wlr_renderer_get_dmabuf_texture_formats(server->renderer) != NULL) {