diff --git a/include/wlr/types/wlr_buffer.h b/include/wlr/types/wlr_buffer.h index 6327bbfb..d305f4d4 100644 --- a/include/wlr/types/wlr_buffer.h +++ b/include/wlr/types/wlr_buffer.h @@ -136,10 +136,15 @@ struct wlr_client_buffer { * client destroys the buffer before it has been released. */ struct wlr_texture *texture; + /** + * The buffer this client buffer was created from. NULL if destroyed. + */ + struct wlr_buffer *source; // private state struct wl_listener resource_destroy; + struct wl_listener source_destroy; // If the client buffer has been created from a wl_shm buffer uint32_t shm_source_format; diff --git a/types/wlr_buffer.c b/types/wlr_buffer.c index 42854b70..ba02f384 100644 --- a/types/wlr_buffer.c +++ b/types/wlr_buffer.c @@ -124,6 +124,7 @@ static struct wlr_client_buffer *client_buffer_from_buffer( static void client_buffer_destroy(struct wlr_buffer *buffer) { struct wlr_client_buffer *client_buffer = client_buffer_from_buffer(buffer); wl_list_remove(&client_buffer->resource_destroy.link); + wl_list_remove(&client_buffer->source_destroy.link); wlr_texture_destroy(client_buffer->texture); free(client_buffer); } @@ -169,6 +170,15 @@ static void client_buffer_resource_handle_destroy(struct wl_listener *listener, // which case we'll read garbage. We decide to accept this risk. } +static void client_buffer_handle_source_destroy(struct wl_listener *listener, + void *data) { + struct wlr_client_buffer *client_buffer = + wl_container_of(listener, client_buffer, source_destroy); + wl_list_remove(&client_buffer->source_destroy.link); + wl_list_init(&client_buffer->source_destroy.link); + client_buffer->source = NULL; +} + static bool buffer_is_shm_client_buffer(struct wlr_buffer *buffer); static struct wlr_shm_client_buffer *shm_client_buffer_from_buffer( struct wlr_buffer *buffer); @@ -224,11 +234,15 @@ struct wlr_client_buffer *wlr_client_buffer_create(struct wlr_buffer *buffer, wlr_buffer_init(&client_buffer->base, &client_buffer_impl, texture->width, texture->height); client_buffer->resource = resource; + client_buffer->source = buffer; client_buffer->texture = texture; wl_resource_add_destroy_listener(resource, &client_buffer->resource_destroy); client_buffer->resource_destroy.notify = client_buffer_resource_handle_destroy; + wl_signal_add(&buffer->events.destroy, &client_buffer->source_destroy); + client_buffer->source_destroy.notify = client_buffer_handle_source_destroy; + if (buffer_is_shm_client_buffer(buffer)) { struct wlr_shm_client_buffer *shm_client_buffer = shm_client_buffer_from_buffer(buffer);