output: defer fake present events until after commit

Since headless and wayland-without-presentation-feedback were firing
present inside their commit impls, present was getting fired before
commit, which is cursed. Defer this with an idle timer so that commit
handlers can run before present handlers.
master
Rose Hudson 1 year ago committed by Alexander Orzechowski
parent a1679c92ce
commit 83af3202f9

@ -71,7 +71,7 @@ static bool output_commit(struct wlr_output *wlr_output,
.commit_seq = wlr_output->commit_seq + 1, .commit_seq = wlr_output->commit_seq + 1,
.presented = true, .presented = true,
}; };
wlr_output_send_present(wlr_output, &present_event); output_defer_present(wlr_output, present_event);
wl_event_source_timer_update(output->frame_timer, output->frame_delay); wl_event_source_timer_update(output->frame_timer, output->frame_delay);
} }

@ -590,7 +590,7 @@ static bool output_commit(struct wlr_output *wlr_output,
.commit_seq = wlr_output->commit_seq + 1, .commit_seq = wlr_output->commit_seq + 1,
.presented = true, .presented = true,
}; };
wlr_output_send_present(wlr_output, &present_event); output_defer_present(wlr_output, present_event);
} }
} }

@ -21,4 +21,6 @@ bool output_cursor_set_texture(struct wlr_output_cursor *cursor,
int dst_width, int dst_height, enum wl_output_transform transform, int dst_width, int dst_height, enum wl_output_transform transform,
int32_t hotspot_x, int32_t hotspot_y); int32_t hotspot_x, int32_t hotspot_y);
void output_defer_present(struct wlr_output *output, struct wlr_output_event_present event);
#endif #endif

@ -927,6 +927,46 @@ void wlr_output_send_present(struct wlr_output *output,
wl_signal_emit_mutable(&output->events.present, event); wl_signal_emit_mutable(&output->events.present, event);
} }
struct deferred_present_event {
struct wlr_output *output;
struct wl_event_source *idle_source;
struct wlr_output_event_present event;
struct wl_listener output_destroy;
};
static void deferred_present_event_destroy(struct deferred_present_event *deferred) {
wl_list_remove(&deferred->output_destroy.link);
free(deferred);
}
static void deferred_present_event_handle_idle(void *data) {
struct deferred_present_event *deferred = data;
wlr_output_send_present(deferred->output, &deferred->event);
deferred_present_event_destroy(deferred);
}
static void deferred_present_event_handle_output_destroy(struct wl_listener *listener, void *data) {
struct deferred_present_event *deferred = wl_container_of(listener, deferred, output_destroy);
wl_event_source_remove(deferred->idle_source);
deferred_present_event_destroy(deferred);
}
void output_defer_present(struct wlr_output *output, struct wlr_output_event_present event) {
struct deferred_present_event *deferred = calloc(1, sizeof(struct wlr_output_event_present));
if (!deferred) {
return;
}
*deferred = (struct deferred_present_event){
.output = output,
.event = event,
};
deferred->output_destroy.notify = deferred_present_event_handle_output_destroy;
wl_signal_add(&output->events.destroy, &deferred->output_destroy);
struct wl_event_loop *ev = wl_display_get_event_loop(output->display);
deferred->idle_source = wl_event_loop_add_idle(ev, deferred_present_event_handle_idle, deferred);
}
void wlr_output_send_request_state(struct wlr_output *output, void wlr_output_send_request_state(struct wlr_output *output,
const struct wlr_output_state *state) { const struct wlr_output_state *state) {
uint32_t unchanged = output_compare_state(output, state); uint32_t unchanged = output_compare_state(output, state);

Loading…
Cancel
Save