+}
+
+static void
+output_repaint_timer_arm(struct weston_compositor *compositor)
+{
+ struct weston_output *output;
+ bool any_should_repaint = false;
+ struct timespec now;
+ int64_t msec_to_next;
+
+ weston_compositor_read_presentation_clock(compositor, &now);
+
+ wl_list_for_each(output, &compositor->output_list, link) {
+ int64_t msec_to_this;
+
+ if (output->repaint_status != REPAINT_SCHEDULED)
+ continue;
+
+ msec_to_this = timespec_sub_to_msec(&output->next_repaint,
+ &now);
+ if (!any_should_repaint || msec_to_this < msec_to_next)
+ msec_to_next = msec_to_this;
+
+ any_should_repaint = true;
+ }
+
+ if (!any_should_repaint)
+ return;
+
+ /* Even if we should repaint immediately, add the minimum 1 ms delay.
+ * This is a workaround to allow coalescing multiple output repaints
+ * particularly from weston_output_finish_frame()
+ * into the same call, which would not happen if we called
+ * output_repaint_timer_handler() directly.
+ */
+ if (msec_to_next < 1)
+ msec_to_next = 1;
+
+ wl_event_source_timer_update(compositor->repaint_timer, msec_to_next);
+}
+
+static int
+output_repaint_timer_handler(void *data)
+{
+ struct weston_compositor *compositor = data;
+ struct weston_output *output;
+ struct timespec now;
+
+ weston_compositor_read_presentation_clock(compositor, &now);
+ wl_list_for_each(output, &compositor->output_list, link)
+ weston_output_maybe_repaint(output, &now);
+
+ output_repaint_timer_arm(compositor);
+