Prevent excessive frame events when compositor doesn't swap buffers

When we send an output frame event, we should not assume that the
compositor is going to call wlr_output_swap_buffers in response to it.
If the compositor does not swap the buffers, the idle event source still
exists and is executed every time the Wayland event loop becomes idle,
which means we send frame events repeatedly until the buffers are
swapped.

This moves the removal of the idle event source out of
wlr_output_swap_buffers and into wlr_output_send_frame, where it is
guaranteed to be removed.
This commit is contained in:
Ryan Dwyer 2018-10-05 20:07:02 +10:00
parent 24a48d4858
commit b7b781ff44
1 changed files with 6 additions and 5 deletions

View File

@ -472,10 +472,6 @@ bool wlr_output_swap_buffers(struct wlr_output *output, struct timespec *when,
wlr_log(WLR_ERROR, "Tried to swap buffers when a frame is pending"); wlr_log(WLR_ERROR, "Tried to swap buffers when a frame is pending");
return false; return false;
} }
if (output->idle_frame != NULL) {
wl_event_source_remove(output->idle_frame);
output->idle_frame = NULL;
}
int width, height; int width, height;
wlr_output_transformed_resolution(output, &width, &height); wlr_output_transformed_resolution(output, &width, &height);
@ -529,7 +525,6 @@ bool wlr_output_swap_buffers(struct wlr_output *output, struct timespec *when,
return false; return false;
} }
output->frame_pending = true;
output->needs_swap = false; output->needs_swap = false;
pixman_region32_clear(&output->damage); pixman_region32_clear(&output->damage);
@ -540,6 +535,12 @@ bool wlr_output_swap_buffers(struct wlr_output *output, struct timespec *when,
void wlr_output_send_frame(struct wlr_output *output) { void wlr_output_send_frame(struct wlr_output *output) {
output->frame_pending = false; output->frame_pending = false;
wlr_signal_emit_safe(&output->events.frame, output); wlr_signal_emit_safe(&output->events.frame, output);
output->frame_pending = true;
if (output->idle_frame != NULL) {
wl_event_source_remove(output->idle_frame);
output->idle_frame = NULL;
}
} }
static void schedule_frame_handle_idle_timer(void *data) { static void schedule_frame_handle_idle_timer(void *data) {