output: replace wlr_output.damage with a damage event

This patch disambiguates the needs_frame event by uncoupling it from
damage. A new separate damage event is emitted when the backend damages
the output (this happens e.g. VT is changed or software cursors are
used). The event specifies the damaged region.

The wlr_output.damage field is removed. wlr_output is no longer
responsible for tracking its own damage, this is wlr_output_damage's
job.

This is a breaking change, but wlr_output_damage users shouldn't need an
update.

Bugs fixed:

- Screen flashes on VT switch
- Cursor damage issues on the X11 and headless backends

Closes: https://github.com/swaywm/sway/issues/5086
This commit is contained in:
Simon Ser 2020-03-12 13:08:57 +01:00 committed by Drew DeVault
parent 07737e85cc
commit e0bbafc253
4 changed files with 43 additions and 14 deletions

View File

@ -138,7 +138,6 @@ struct wlr_output {
bool needs_frame; bool needs_frame;
// damage for cursors and fullscreen surface, in output-local coordinates // damage for cursors and fullscreen surface, in output-local coordinates
pixman_region32_t damage;
bool frame_pending; bool frame_pending;
float transform_matrix[9]; float transform_matrix[9];
@ -150,8 +149,11 @@ struct wlr_output {
struct { struct {
// Request to render a frame // Request to render a frame
struct wl_signal frame; struct wl_signal frame;
// Emitted when buffers need to be swapped (because software cursors or // Emitted when software cursors or backend-specific logic damage the
// fullscreen damage or because of backend-specific logic) // 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; struct wl_signal needs_frame;
// Emitted right before commit // Emitted right before commit
struct wl_signal precommit; // wlr_output_event_precommit struct wl_signal precommit; // wlr_output_event_precommit
@ -181,6 +183,11 @@ struct wlr_output {
void *data; 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_event_precommit {
struct wlr_output *output; struct wlr_output *output;
struct timespec *when; struct timespec *when;

View File

@ -52,6 +52,7 @@ struct wlr_output_damage {
struct wl_listener output_transform; struct wl_listener output_transform;
struct wl_listener output_scale; struct wl_listener output_scale;
struct wl_listener output_needs_frame; struct wl_listener output_needs_frame;
struct wl_listener output_damage;
struct wl_listener output_frame; struct wl_listener output_frame;
struct wl_listener output_commit; struct wl_listener output_commit;
}; };

View File

@ -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->cursors);
wl_list_init(&output->resources); wl_list_init(&output->resources);
wl_signal_init(&output->events.frame); wl_signal_init(&output->events.frame);
wl_signal_init(&output->events.damage);
wl_signal_init(&output->events.needs_frame); wl_signal_init(&output->events.needs_frame);
wl_signal_init(&output->events.precommit); wl_signal_init(&output->events.precommit);
wl_signal_init(&output->events.commit); 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.transform);
wl_signal_init(&output->events.description); wl_signal_init(&output->events.description);
wl_signal_init(&output->events.destroy); wl_signal_init(&output->events.destroy);
pixman_region32_init(&output->damage);
pixman_region32_init(&output->pending.damage); pixman_region32_init(&output->pending.damage);
const char *no_hardware_cursors = getenv("WLR_NO_HARDWARE_CURSORS"); 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); free(output->description);
pixman_region32_fini(&output->pending.damage); pixman_region32_fini(&output->pending.damage);
pixman_region32_fini(&output->damage);
if (output->impl && output->impl->destroy) { if (output->impl && output->impl->destroy) {
output->impl->destroy(output); output->impl->destroy(output);
@ -562,7 +561,6 @@ bool wlr_output_commit(struct wlr_output *output) {
if (output->pending.committed & WLR_OUTPUT_STATE_BUFFER) { if (output->pending.committed & WLR_OUTPUT_STATE_BUFFER) {
output->frame_pending = true; output->frame_pending = true;
output->needs_frame = false; output->needs_frame = false;
pixman_region32_clear(&output->damage);
} }
output_state_clear(&output->pending); output_state_clear(&output->pending);
@ -697,9 +695,16 @@ void wlr_output_damage_whole(struct wlr_output *output) {
int width, height; int width, height;
wlr_output_transformed_resolution(output, &width, &height); wlr_output_transformed_resolution(output, &width, &height);
pixman_region32_union_rect(&output->damage, &output->damage, 0, 0, pixman_region32_t damage;
width, height); pixman_region32_init_rect(&damage, 0, 0, width, height);
wlr_output_update_needs_frame(output);
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) { 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) { static void output_cursor_damage_whole(struct wlr_output_cursor *cursor) {
struct wlr_box box; struct wlr_box box;
output_cursor_get_box(cursor, &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); pixman_region32_t damage;
wlr_output_update_needs_frame(cursor->output); 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) { static void output_cursor_reset(struct wlr_output_cursor *cursor) {

View File

@ -35,11 +35,16 @@ static void output_handle_needs_frame(struct wl_listener *listener,
void *data) { void *data) {
struct wlr_output_damage *output_damage = struct wlr_output_damage *output_damage =
wl_container_of(listener, output_damage, output_needs_frame); 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); 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) { static void output_handle_frame(struct wl_listener *listener, void *data) {
struct wlr_output_damage *output_damage = struct wlr_output_damage *output_damage =
wl_container_of(listener, output_damage, output_frame); 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; output_damage->output_scale.notify = output_handle_scale;
wl_signal_add(&output->events.needs_frame, &output_damage->output_needs_frame); wl_signal_add(&output->events.needs_frame, &output_damage->output_needs_frame);
output_damage->output_needs_frame.notify = output_handle_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); wl_signal_add(&output->events.frame, &output_damage->output_frame);
output_damage->output_frame.notify = output_handle_frame; output_damage->output_frame.notify = output_handle_frame;
wl_signal_add(&output->events.commit, &output_damage->output_commit); 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_transform.link);
wl_list_remove(&output_damage->output_scale.link); wl_list_remove(&output_damage->output_scale.link);
wl_list_remove(&output_damage->output_needs_frame.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_frame.link);
wl_list_remove(&output_damage->output_commit.link); wl_list_remove(&output_damage->output_commit.link);
pixman_region32_fini(&output_damage->current); pixman_region32_fini(&output_damage->current);