diff options
author | Simon Ser <contact@emersion.fr> | 2024-03-14 13:54:08 +0100 |
---|---|---|
committer | Kenny Levinsen <kl@kl.wtf> | 2024-03-14 22:55:46 +0100 |
commit | 3bc75221bc0074b2e96e14cb88140c95406472c3 (patch) | |
tree | f8f63fb9a2192c0953fe787c9d018dc03d090ad6 /sway/server.c | |
parent | server: fix wlr_seat use-after-free on exit (diff) | |
download | sway-3bc75221bc0074b2e96e14cb88140c95406472c3.tar.gz sway-3bc75221bc0074b2e96e14cb88140c95406472c3.tar.zst sway-3bc75221bc0074b2e96e14cb88140c95406472c3.zip |
Re-create renderer when lost
Diffstat (limited to 'sway/server.c')
-rw-r--r-- | sway/server.c | 42 |
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 | ||
175 | static 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 | |||
175 | bool server_init(struct sway_server *server) { | 214 | bool 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) { |