commit 3bc75221bc0074b2e96e14cb88140c95406472c3
parent 2b08e79061db583d0ffe46114c48f958a0d3e6ed
Author: Simon Ser <contact@emersion.fr>
Date: Thu, 14 Mar 2024 13:54:08 +0100
Re-create renderer when lost
Diffstat:
2 files changed, 43 insertions(+), 0 deletions(-)
diff --git a/include/sway/server.h b/include/sway/server.h
@@ -46,6 +46,7 @@ struct sway_server {
struct wl_listener new_output;
struct wl_listener output_layout_change;
+ struct wl_listener renderer_lost;
struct wlr_idle_notifier_v1 *idle_notifier_v1;
struct sway_idle_inhibit_manager_v1 idle_inhibit_manager_v1;
diff --git a/sway/server.c b/sway/server.c
@@ -172,6 +172,45 @@ static void detect_proprietary(struct wlr_backend *backend, void *data) {
drmFreeVersion(version);
}
+static void handle_renderer_lost(struct wl_listener *listener, void *data) {
+ struct sway_server *server = wl_container_of(listener, server, renderer_lost);
+
+ sway_log(SWAY_INFO, "Re-creating renderer after GPU reset");
+
+ struct wlr_renderer *renderer = wlr_renderer_autocreate(server->backend);
+ if (renderer == NULL) {
+ sway_log(SWAY_ERROR, "Unable to create renderer");
+ return;
+ }
+
+ struct wlr_allocator *allocator =
+ wlr_allocator_autocreate(server->backend, renderer);
+ if (allocator == NULL) {
+ sway_log(SWAY_ERROR, "Unable to create allocator");
+ wlr_renderer_destroy(renderer);
+ return;
+ }
+
+ struct wlr_renderer *old_renderer = server->renderer;
+ struct wlr_allocator *old_allocator = server->allocator;
+ server->renderer = renderer;
+ server->allocator = allocator;
+
+ wl_list_remove(&server->renderer_lost.link);
+ wl_signal_add(&server->renderer->events.lost, &server->renderer_lost);
+
+ wlr_compositor_set_renderer(server->compositor, renderer);
+
+ for (int i = 0; i < root->outputs->length; ++i) {
+ struct sway_output *output = root->outputs->items[i];
+ wlr_output_init_render(output->wlr_output,
+ server->allocator, server->renderer);
+ }
+
+ wlr_allocator_destroy(old_allocator);
+ wlr_renderer_destroy(old_renderer);
+}
+
bool server_init(struct sway_server *server) {
sway_log(SWAY_DEBUG, "Initializing Wayland server");
server->wl_display = wl_display_create();
@@ -195,6 +234,9 @@ bool server_init(struct sway_server *server) {
return false;
}
+ server->renderer_lost.notify = handle_renderer_lost;
+ wl_signal_add(&server->renderer->events.lost, &server->renderer_lost);
+
wlr_renderer_init_wl_shm(server->renderer, server->wl_display);
if (wlr_renderer_get_dmabuf_texture_formats(server->renderer) != NULL) {