diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index 436bcac3..9d6e85b3 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -138,7 +138,6 @@ struct wlr_output { bool needs_frame; // damage for cursors and fullscreen surface, in output-local coordinates - pixman_region32_t damage; bool frame_pending; float transform_matrix[9]; @@ -150,8 +149,11 @@ struct wlr_output { struct { // Request to render a frame struct wl_signal frame; - // Emitted when buffers need to be swapped (because software cursors or - // fullscreen damage or because of backend-specific logic) + // Emitted when software cursors or backend-specific logic damage the + // output + struct wl_signal damage; // wlr_output_event_damage + // Emitted when a new frame needs to be committed (because of + // backend-specific logic) struct wl_signal needs_frame; // Emitted right before commit struct wl_signal precommit; // wlr_output_event_precommit @@ -181,6 +183,11 @@ struct wlr_output { void *data; }; +struct wlr_output_event_damage { + struct wlr_output *output; + pixman_region32_t *damage; // output-buffer-local coordinates +}; + struct wlr_output_event_precommit { struct wlr_output *output; struct timespec *when; diff --git a/include/wlr/types/wlr_output_damage.h b/include/wlr/types/wlr_output_damage.h index 708ee9b6..4cdb0a54 100644 --- a/include/wlr/types/wlr_output_damage.h +++ b/include/wlr/types/wlr_output_damage.h @@ -52,6 +52,7 @@ struct wlr_output_damage { struct wl_listener output_transform; struct wl_listener output_scale; struct wl_listener output_needs_frame; + struct wl_listener output_damage; struct wl_listener output_frame; struct wl_listener output_commit; }; diff --git a/types/wlr_output.c b/types/wlr_output.c index f9edd29a..4855fa4b 100644 --- a/types/wlr_output.c +++ b/types/wlr_output.c @@ -328,6 +328,7 @@ void wlr_output_init(struct wlr_output *output, struct wlr_backend *backend, wl_list_init(&output->cursors); wl_list_init(&output->resources); wl_signal_init(&output->events.frame); + wl_signal_init(&output->events.damage); wl_signal_init(&output->events.needs_frame); wl_signal_init(&output->events.precommit); wl_signal_init(&output->events.commit); @@ -338,7 +339,6 @@ void wlr_output_init(struct wlr_output *output, struct wlr_backend *backend, wl_signal_init(&output->events.transform); wl_signal_init(&output->events.description); wl_signal_init(&output->events.destroy); - pixman_region32_init(&output->damage); pixman_region32_init(&output->pending.damage); const char *no_hardware_cursors = getenv("WLR_NO_HARDWARE_CURSORS"); @@ -382,7 +382,6 @@ void wlr_output_destroy(struct wlr_output *output) { free(output->description); pixman_region32_fini(&output->pending.damage); - pixman_region32_fini(&output->damage); if (output->impl && output->impl->destroy) { output->impl->destroy(output); @@ -562,7 +561,6 @@ bool wlr_output_commit(struct wlr_output *output) { if (output->pending.committed & WLR_OUTPUT_STATE_BUFFER) { output->frame_pending = true; output->needs_frame = false; - pixman_region32_clear(&output->damage); } output_state_clear(&output->pending); @@ -697,9 +695,16 @@ void wlr_output_damage_whole(struct wlr_output *output) { int width, height; wlr_output_transformed_resolution(output, &width, &height); - pixman_region32_union_rect(&output->damage, &output->damage, 0, 0, - width, height); - wlr_output_update_needs_frame(output); + pixman_region32_t damage; + pixman_region32_init_rect(&damage, 0, 0, width, height); + + struct wlr_output_event_damage event = { + .output = output, + .damage = &damage, + }; + wlr_signal_emit_safe(&output->events.damage, &event); + + pixman_region32_fini(&damage); } struct wlr_output *wlr_output_from_resource(struct wl_resource *resource) { @@ -855,9 +860,17 @@ static void output_cursor_get_box(struct wlr_output_cursor *cursor, static void output_cursor_damage_whole(struct wlr_output_cursor *cursor) { struct wlr_box box; output_cursor_get_box(cursor, &box); - pixman_region32_union_rect(&cursor->output->damage, &cursor->output->damage, - box.x, box.y, box.width, box.height); - wlr_output_update_needs_frame(cursor->output); + + pixman_region32_t damage; + pixman_region32_init_rect(&damage, box.x, box.y, box.width, box.height); + + struct wlr_output_event_damage event = { + .output = cursor->output, + .damage = &damage, + }; + wlr_signal_emit_safe(&cursor->output->events.damage, &event); + + pixman_region32_fini(&damage); } static void output_cursor_reset(struct wlr_output_cursor *cursor) { diff --git a/types/wlr_output_damage.c b/types/wlr_output_damage.c index 8c288e44..ade0375e 100644 --- a/types/wlr_output_damage.c +++ b/types/wlr_output_damage.c @@ -35,11 +35,16 @@ static void output_handle_needs_frame(struct wl_listener *listener, void *data) { struct wlr_output_damage *output_damage = wl_container_of(listener, output_damage, output_needs_frame); - pixman_region32_union(&output_damage->current, &output_damage->current, - &output_damage->output->damage); wlr_output_schedule_frame(output_damage->output); } +static void output_handle_damage(struct wl_listener *listener, void *data) { + struct wlr_output_damage *output_damage = + wl_container_of(listener, output_damage, output_damage); + struct wlr_output_event_damage *event = data; + wlr_output_damage_add(output_damage, event->damage); +} + static void output_handle_frame(struct wl_listener *listener, void *data) { struct wlr_output_damage *output_damage = wl_container_of(listener, output_damage, output_frame); @@ -108,6 +113,8 @@ struct wlr_output_damage *wlr_output_damage_create(struct wlr_output *output) { output_damage->output_scale.notify = output_handle_scale; wl_signal_add(&output->events.needs_frame, &output_damage->output_needs_frame); output_damage->output_needs_frame.notify = output_handle_needs_frame; + wl_signal_add(&output->events.damage, &output_damage->output_damage); + output_damage->output_damage.notify = output_handle_damage; wl_signal_add(&output->events.frame, &output_damage->output_frame); output_damage->output_frame.notify = output_handle_frame; wl_signal_add(&output->events.commit, &output_damage->output_commit); @@ -126,6 +133,7 @@ void wlr_output_damage_destroy(struct wlr_output_damage *output_damage) { wl_list_remove(&output_damage->output_transform.link); wl_list_remove(&output_damage->output_scale.link); wl_list_remove(&output_damage->output_needs_frame.link); + wl_list_remove(&output_damage->output_damage.link); wl_list_remove(&output_damage->output_frame.link); wl_list_remove(&output_damage->output_commit.link); pixman_region32_fini(&output_damage->current);