[PATCH weston 4/5] compositor: add repaint delay timer

Pekka Paalanen ppaalanen at gmail.com
Thu Feb 12 05:30:16 PST 2015


From: Pekka Paalanen <pekka.paalanen at collabora.co.uk>

This timer delays the output_repaint towards the end of the refresh
period, reducing the time from repaint to present.

The length of the repaint window can be set in weston.ini.

Signed-off-by: Pekka Paalanen <pekka.paalanen at collabora.co.uk>
---
 man/weston.ini.man | 10 ++++++++++
 src/compositor.c   | 49 +++++++++++++++++++++++++++++++++++++++++++++----
 src/compositor.h   |  2 ++
 3 files changed, 57 insertions(+), 4 deletions(-)

diff --git a/man/weston.ini.man b/man/weston.ini.man
index 7a353c9..d7df0e4 100644
--- a/man/weston.ini.man
+++ b/man/weston.ini.man
@@ -137,6 +137,16 @@ directory are:
 .fi
 .RE
 .TP 7
+.BI "repaint-window=" N
+Set the approximate length of the repaint window in milliseconds. The repaint
+window is used to control and reduce the output latency for clients. If the
+window is longer than the output refresh period, the repaint will be done
+immediately when the previous repaint finishes, not processing client requests
+in between. If the repaint window is too short, the compositor may miss the
+target vertical blank, increasing output latency. The default value is 7
+milliseconds. The allowed range is from -10 to 1000 milliseconds. Using a
+negative value will force the compositor to always miss the target vblank.
+.TP 7
 .BI "gbm-format="format
 sets the GBM format used for the framebuffer for the GBM backend. Can be
 .B xrgb8888,
diff --git a/src/compositor.c b/src/compositor.c
index b0bca24..aed6893 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -62,6 +62,8 @@
 #include "git-version.h"
 #include "version.h"
 
+#define DEFAULT_REPAINT_WINDOW 7 /* milliseconds */
+
 static struct wl_list child_process_list;
 static struct weston_compositor *segv_compositor;
 
@@ -2135,13 +2137,28 @@ weston_output_schedule_repaint_reset(struct weston_output *output)
 				     weston_compositor_read_input, compositor);
 }
 
+static int
+output_repaint_delay_handler(void *data)
+{
+	struct weston_output *output = data;
+	struct weston_compositor *compositor = output->compositor;
+
+	if (compositor->state != WESTON_COMPOSITOR_SLEEPING &&
+	    compositor->state != WESTON_COMPOSITOR_OFFSCREEN &&
+	    weston_output_repaint(output) == 0)
+		return 0;
+
+	weston_output_schedule_repaint_reset(output);
+
+	return 0;
+}
+
 WL_EXPORT void
 weston_output_finish_frame(struct weston_output *output,
 			   const struct timespec *stamp,
 			   uint32_t presented_flags)
 {
 	struct weston_compositor *compositor = output->compositor;
-	int r;
 	uint32_t refresh_nsec;
 
 	TL_POINT("core_repaint_finished", TLP_OUTPUT(output),
@@ -2158,9 +2175,14 @@ weston_output_finish_frame(struct weston_output *output,
 	if (output->repaint_needed &&
 	    compositor->state != WESTON_COMPOSITOR_SLEEPING &&
 	    compositor->state != WESTON_COMPOSITOR_OFFSCREEN) {
-		r = weston_output_repaint(output);
-		if (!r)
-			return;
+		int msec = refresh_nsec / 1000000;
+
+		msec -= compositor->repaint_msec;
+		if (msec < 1)
+			output_repaint_delay_handler(output);
+		else
+			wl_event_source_timer_update(output->repaint_delay_timer, msec);
+		return;
 	}
 
 	weston_output_schedule_repaint_reset(output);
@@ -3480,6 +3502,8 @@ weston_output_destroy(struct weston_output *output)
 
 	output->destroying = 1;
 
+	wl_event_source_remove(output->repaint_delay_timer);
+
 	weston_presentation_feedback_discard_list(&output->feedback_list);
 
 	weston_compositor_remove_output(output->compositor, output);
@@ -3672,6 +3696,8 @@ weston_output_init(struct weston_output *output, struct weston_compositor *c,
 		   int x, int y, int mm_width, int mm_height, uint32_t transform,
 		   int32_t scale)
 {
+	struct wl_event_loop *loop;
+
 	output->compositor = c;
 	output->x = x;
 	output->y = y;
@@ -3692,6 +3718,10 @@ weston_output_init(struct weston_output *output, struct weston_compositor *c,
 	wl_list_init(&output->resource_list);
 	wl_list_init(&output->feedback_list);
 
+	loop = wl_display_get_event_loop(c->wl_display);
+	output->repaint_delay_timer =
+		wl_event_loop_add_timer(loop, output_repaint_delay_handler, output);
+
 	output->id = ffs(~output->compositor->output_id_pool) - 1;
 	output->compositor->output_id_pool |= 1 << output->id;
 
@@ -4206,6 +4236,17 @@ weston_compositor_init(struct weston_compositor *ec,
 	weston_compositor_add_debug_binding(ec, KEY_T,
 					    timeline_key_binding_handler, ec);
 
+	s = weston_config_get_section(ec->config, "core", NULL, NULL);
+	weston_config_section_get_int(s, "repaint-window", &ec->repaint_msec,
+				      DEFAULT_REPAINT_WINDOW);
+	if (ec->repaint_msec < -10 || ec->repaint_msec > 1000) {
+		weston_log("Invalid repaint_window value in config: %d\n",
+			   ec->repaint_msec);
+		ec->repaint_msec = DEFAULT_REPAINT_WINDOW;
+	}
+	weston_log("Output repaint window is %d ms maximum.\n",
+		   ec->repaint_msec);
+
 	weston_compositor_schedule_repaint(ec);
 
 	return 0;
diff --git a/src/compositor.h b/src/compositor.h
index 5c0ea74..2da8387 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -194,6 +194,7 @@ struct weston_output {
 	pixman_region32_t previous_damage;
 	int repaint_needed;
 	int repaint_scheduled;
+	struct wl_event_source *repaint_delay_timer;
 	struct weston_output_zoom zoom;
 	int dirty;
 	struct wl_signal frame_signal;
@@ -667,6 +668,7 @@ struct weston_compositor {
 	int32_t kb_repeat_delay;
 
 	clockid_t presentation_clock;
+	int32_t repaint_msec;
 
 	int exit_code;
 };
-- 
2.0.5



More information about the wayland-devel mailing list