diff --git a/include/wlr/types/wlr_compositor.h b/include/wlr/types/wlr_compositor.h index 6524aea25..dc54a5f12 100644 --- a/include/wlr/types/wlr_compositor.h +++ b/include/wlr/types/wlr_compositor.h @@ -538,6 +538,12 @@ void wlr_surface_synced_finish(struct wlr_surface_synced *synced); void *wlr_surface_synced_get_state(struct wlr_surface_synced *synced, const struct wlr_surface_state *state); +/* + * Consumes buffer and damage state of the buffer so that the compositor may + * drop references to any of these resources. + */ +void wlr_surface_consume(struct wlr_surface *surface); + /** * Get a Pixman region from a wl_region resource. */ diff --git a/types/wlr_compositor.c b/types/wlr_compositor.c index 24bdaa8fc..6f7c5061f 100644 --- a/types/wlr_compositor.c +++ b/types/wlr_compositor.c @@ -419,6 +419,10 @@ static void surface_apply_damage(struct wlr_surface *surface) { return; } + // lock the buffer during the commit so that everything watching the surface + // can have a chance to take a look at the buffer. + wlr_buffer_lock(surface->current.buffer); + wl_signal_add(&surface->current.buffer->events.release, &surface->current_buffer_release); @@ -427,6 +431,7 @@ static void surface_apply_damage(struct wlr_surface *surface) { if (surface->buffer != NULL) { if (wlr_client_buffer_apply_damage(surface->buffer, surface->current.buffer, &surface->buffer_damage)) { + wlr_surface_consume(surface); return; } } @@ -437,6 +442,7 @@ static void surface_apply_damage(struct wlr_surface *surface) { struct wlr_client_buffer *buffer = wlr_client_buffer_create( surface->current.buffer, surface->compositor->renderer); + wlr_surface_consume(surface); if (buffer == NULL) { wlr_log(WLR_ERROR, "Failed to upload buffer"); @@ -783,6 +789,15 @@ static void surface_handle_current_buffer_release(struct wl_listener *listener, surface_clean_state(surface); } +void wlr_surface_consume(struct wlr_surface *surface) { + if (surface->consumed || !surface->current.buffer) { + return; + } + + surface->consumed = true; + wlr_buffer_unlock(surface->current.buffer); +} + static struct wlr_surface *surface_create(struct wl_client *client, uint32_t version, uint32_t id, struct wlr_compositor *compositor) { struct wlr_surface *surface = calloc(1, sizeof(*surface));