mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2026-04-14 08:22:25 -04:00
wlr_compositor: release state on buffer release
wlr_compositor will now wait for the current buffer to be released before clearing relevant state. For now, this will always happen at the end of the commit so there should be no functional change here.
This commit is contained in:
parent
06cd96b832
commit
42c395f39c
2 changed files with 40 additions and 5 deletions
|
|
@ -239,6 +239,7 @@ struct wlr_surface {
|
||||||
// private state
|
// private state
|
||||||
|
|
||||||
struct wl_listener role_resource_destroy;
|
struct wl_listener role_resource_destroy;
|
||||||
|
struct wl_listener current_buffer_release;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
int32_t scale;
|
int32_t scale;
|
||||||
|
|
@ -250,6 +251,7 @@ struct wlr_surface {
|
||||||
bool unmap_commit;
|
bool unmap_commit;
|
||||||
|
|
||||||
bool opaque;
|
bool opaque;
|
||||||
|
bool consumed;
|
||||||
|
|
||||||
bool handling_commit;
|
bool handling_commit;
|
||||||
bool pending_rejected;
|
bool pending_rejected;
|
||||||
|
|
|
||||||
|
|
@ -405,8 +405,12 @@ static void surface_state_move(struct wlr_surface_state *state,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void surface_apply_damage(struct wlr_surface *surface) {
|
static void surface_apply_damage(struct wlr_surface *surface) {
|
||||||
|
wl_list_remove(&surface->current_buffer_release.link);
|
||||||
|
|
||||||
if (surface->current.buffer == NULL) {
|
if (surface->current.buffer == NULL) {
|
||||||
// NULL commit
|
// NULL commit
|
||||||
|
wl_list_init(&surface->current_buffer_release.link);
|
||||||
|
|
||||||
if (surface->buffer != NULL) {
|
if (surface->buffer != NULL) {
|
||||||
wlr_buffer_unlock(&surface->buffer->base);
|
wlr_buffer_unlock(&surface->buffer->base);
|
||||||
}
|
}
|
||||||
|
|
@ -415,13 +419,14 @@ static void surface_apply_damage(struct wlr_surface *surface) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wl_signal_add(&surface->current.buffer->events.release,
|
||||||
|
&surface->current_buffer_release);
|
||||||
|
|
||||||
surface->opaque = buffer_is_opaque(surface->current.buffer);
|
surface->opaque = buffer_is_opaque(surface->current.buffer);
|
||||||
|
|
||||||
if (surface->buffer != NULL) {
|
if (surface->buffer != NULL) {
|
||||||
if (wlr_client_buffer_apply_damage(surface->buffer,
|
if (wlr_client_buffer_apply_damage(surface->buffer,
|
||||||
surface->current.buffer, &surface->buffer_damage)) {
|
surface->current.buffer, &surface->buffer_damage)) {
|
||||||
wlr_buffer_unlock(surface->current.buffer);
|
|
||||||
surface->current.buffer = NULL;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -508,10 +513,26 @@ error:
|
||||||
wl_resource_post_no_memory(surface->resource);
|
wl_resource_post_no_memory(surface->resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void surface_clean_state(struct wlr_surface *surface) {
|
||||||
|
assert(surface->consumed);
|
||||||
|
|
||||||
|
wl_list_remove(&surface->current_buffer_release.link);
|
||||||
|
wl_list_init(&surface->current_buffer_release.link);
|
||||||
|
pixman_region32_clear(&surface->buffer_damage);
|
||||||
|
surface->current.buffer = NULL;
|
||||||
|
surface->consumed = false;
|
||||||
|
}
|
||||||
|
|
||||||
static void surface_commit_state(struct wlr_surface *surface,
|
static void surface_commit_state(struct wlr_surface *surface,
|
||||||
struct wlr_surface_state *next) {
|
struct wlr_surface_state *next) {
|
||||||
assert(next->cached_state_locks == 0);
|
assert(next->cached_state_locks == 0);
|
||||||
|
|
||||||
|
// if the surface was consumed that means we don't own the current buffer
|
||||||
|
// anymore.
|
||||||
|
if (surface->consumed) {
|
||||||
|
surface_clean_state(surface);
|
||||||
|
}
|
||||||
|
|
||||||
bool invalid_buffer = next->committed & WLR_SURFACE_STATE_BUFFER;
|
bool invalid_buffer = next->committed & WLR_SURFACE_STATE_BUFFER;
|
||||||
|
|
||||||
if (invalid_buffer && next->buffer == NULL) {
|
if (invalid_buffer && next->buffer == NULL) {
|
||||||
|
|
@ -562,10 +583,8 @@ static void surface_commit_state(struct wlr_surface *surface,
|
||||||
// Release the buffer after emitting the commit event, so that listeners can
|
// Release the buffer after emitting the commit event, so that listeners can
|
||||||
// access it. Don't leave the buffer locked so that wl_shm buffers can be
|
// access it. Don't leave the buffer locked so that wl_shm buffers can be
|
||||||
// released immediately on commit when they are uploaded to the GPU.
|
// released immediately on commit when they are uploaded to the GPU.
|
||||||
|
surface->consumed = true;
|
||||||
wlr_buffer_unlock(surface->current.buffer);
|
wlr_buffer_unlock(surface->current.buffer);
|
||||||
surface->current.buffer = NULL;
|
|
||||||
|
|
||||||
pixman_region32_clear(&surface->buffer_damage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void surface_handle_commit(struct wl_client *client,
|
static void surface_handle_commit(struct wl_client *client,
|
||||||
|
|
@ -720,6 +739,10 @@ static void surface_destroy_role_object(struct wlr_surface *surface);
|
||||||
static void surface_handle_resource_destroy(struct wl_resource *resource) {
|
static void surface_handle_resource_destroy(struct wl_resource *resource) {
|
||||||
struct wlr_surface *surface = wlr_surface_from_resource(resource);
|
struct wlr_surface *surface = wlr_surface_from_resource(resource);
|
||||||
|
|
||||||
|
if (surface->consumed) {
|
||||||
|
surface_clean_state(surface);
|
||||||
|
}
|
||||||
|
|
||||||
struct wlr_surface_output *surface_output, *surface_output_tmp;
|
struct wlr_surface_output *surface_output, *surface_output_tmp;
|
||||||
wl_list_for_each_safe(surface_output, surface_output_tmp,
|
wl_list_for_each_safe(surface_output, surface_output_tmp,
|
||||||
&surface->current_outputs, link) {
|
&surface->current_outputs, link) {
|
||||||
|
|
@ -738,6 +761,7 @@ static void surface_handle_resource_destroy(struct wl_resource *resource) {
|
||||||
surface_state_destroy_cached(cached, surface);
|
surface_state_destroy_cached(cached, surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wl_list_remove(&surface->current_buffer_release.link);
|
||||||
wl_list_remove(&surface->role_resource_destroy.link);
|
wl_list_remove(&surface->role_resource_destroy.link);
|
||||||
|
|
||||||
wl_list_remove(&surface->pending_buffer_resource_destroy.link);
|
wl_list_remove(&surface->pending_buffer_resource_destroy.link);
|
||||||
|
|
@ -753,6 +777,12 @@ static void surface_handle_resource_destroy(struct wl_resource *resource) {
|
||||||
free(surface);
|
free(surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void surface_handle_current_buffer_release(struct wl_listener *listener,
|
||||||
|
void *data) {
|
||||||
|
struct wlr_surface *surface = wl_container_of(listener, surface, current_buffer_release);
|
||||||
|
surface_clean_state(surface);
|
||||||
|
}
|
||||||
|
|
||||||
static struct wlr_surface *surface_create(struct wl_client *client,
|
static struct wlr_surface *surface_create(struct wl_client *client,
|
||||||
uint32_t version, uint32_t id, struct wlr_compositor *compositor) {
|
uint32_t version, uint32_t id, struct wlr_compositor *compositor) {
|
||||||
struct wlr_surface *surface = calloc(1, sizeof(*surface));
|
struct wlr_surface *surface = calloc(1, sizeof(*surface));
|
||||||
|
|
@ -797,6 +827,9 @@ static struct wlr_surface *surface_create(struct wl_client *client,
|
||||||
surface->pending_buffer_resource_destroy.notify = pending_buffer_resource_handle_destroy;
|
surface->pending_buffer_resource_destroy.notify = pending_buffer_resource_handle_destroy;
|
||||||
wl_list_init(&surface->pending_buffer_resource_destroy.link);
|
wl_list_init(&surface->pending_buffer_resource_destroy.link);
|
||||||
|
|
||||||
|
surface->current_buffer_release.notify = surface_handle_current_buffer_release;
|
||||||
|
wl_list_init(&surface->current_buffer_release.link);
|
||||||
|
|
||||||
return surface;
|
return surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue