mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2026-05-07 02:38:04 +02:00
wlr_compositor: Kill the client if we cannot accept the buffer
When the client commits a new buffer, we may need to instantiate a new wlr_client_buffer which may cause us to import the buffer into our active renderer, which may fail. If the import fails, we leave the old buffer behind but otherwise proceed as normal. If the client is resizing its window and we fail to apply a buffer of a new size, while the client is also applying a suitable viewport src_box for the new buffer size, we will end up with an inconsistent surface state that will later lead to assert. Rather than have an inconsistent surface state that can cause the entire display server to crash on asserts later, sacrifice the client. We might be able to do something smarter in the future. Fixes: https://gitlab.freedesktop.org/wlroots/wlroots/-/work_items/4079 Signed-off-by: Kenny Levinsen <kl@kl.wtf>
This commit is contained in:
parent
70d99eefef
commit
6183b374dd
1 changed files with 12 additions and 7 deletions
|
|
@ -404,7 +404,7 @@ static void surface_state_move(struct wlr_surface_state *state,
|
|||
next->cached_state_locks = 0;
|
||||
}
|
||||
|
||||
static void surface_apply_damage(struct wlr_surface *surface) {
|
||||
static bool surface_apply_damage(struct wlr_surface *surface) {
|
||||
if (surface->current.buffer == NULL) {
|
||||
// NULL commit
|
||||
if (surface->buffer != NULL) {
|
||||
|
|
@ -412,7 +412,7 @@ static void surface_apply_damage(struct wlr_surface *surface) {
|
|||
}
|
||||
surface->buffer = NULL;
|
||||
surface->opaque = false;
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
surface->opaque = wlr_buffer_is_opaque(surface->current.buffer);
|
||||
|
|
@ -422,12 +422,12 @@ static void surface_apply_damage(struct wlr_surface *surface) {
|
|||
surface->current.buffer, &surface->buffer_damage)) {
|
||||
wlr_buffer_unlock(surface->current.buffer);
|
||||
surface->current.buffer = NULL;
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (surface->compositor->renderer == NULL) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
struct wlr_client_buffer *buffer = wlr_client_buffer_create(
|
||||
|
|
@ -435,13 +435,14 @@ static void surface_apply_damage(struct wlr_surface *surface) {
|
|||
|
||||
if (buffer == NULL) {
|
||||
wlr_log(WLR_ERROR, "Failed to upload buffer");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (surface->buffer != NULL) {
|
||||
wlr_buffer_unlock(&surface->buffer->base);
|
||||
}
|
||||
surface->buffer = buffer;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void surface_update_opaque_region(struct wlr_surface *surface) {
|
||||
|
|
@ -532,8 +533,12 @@ static void surface_commit_state(struct wlr_surface *surface,
|
|||
|
||||
surface_state_move(&surface->current, next, surface);
|
||||
|
||||
if (invalid_buffer) {
|
||||
surface_apply_damage(surface);
|
||||
if (invalid_buffer && !surface_apply_damage(surface)) {
|
||||
// We could not update the buffer, which means inconsistent surface
|
||||
// state. If we keep going we risk hitting asserts, so let's play it
|
||||
// safe and kill the client for now.
|
||||
wl_resource_post_no_memory(surface->resource);
|
||||
return;
|
||||
}
|
||||
surface_update_opaque_region(surface);
|
||||
surface_update_input_region(surface);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue