Re-create renderer when lost

This commit is contained in:
Simon Ser 2024-03-14 13:54:08 +01:00 committed by Kenny Levinsen
parent 2b08e79061
commit 3bc75221bc
2 changed files with 43 additions and 0 deletions

View file

@ -46,6 +46,7 @@ struct sway_server {
struct wl_listener new_output; struct wl_listener new_output;
struct wl_listener output_layout_change; struct wl_listener output_layout_change;
struct wl_listener renderer_lost;
struct wlr_idle_notifier_v1 *idle_notifier_v1; struct wlr_idle_notifier_v1 *idle_notifier_v1;
struct sway_idle_inhibit_manager_v1 idle_inhibit_manager_v1; struct sway_idle_inhibit_manager_v1 idle_inhibit_manager_v1;

View file

@ -172,6 +172,45 @@ static void detect_proprietary(struct wlr_backend *backend, void *data) {
drmFreeVersion(version); 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) { bool server_init(struct sway_server *server) {
sway_log(SWAY_DEBUG, "Initializing Wayland server"); sway_log(SWAY_DEBUG, "Initializing Wayland server");
server->wl_display = wl_display_create(); server->wl_display = wl_display_create();
@ -195,6 +234,9 @@ bool server_init(struct sway_server *server) {
return false; 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); wlr_renderer_init_wl_shm(server->renderer, server->wl_display);
if (wlr_renderer_get_dmabuf_texture_formats(server->renderer) != NULL) { if (wlr_renderer_get_dmabuf_texture_formats(server->renderer) != NULL) {