[PATCH weston v2 11/11] Allow backends to group repaint flushes

Daniel Stone daniels at collabora.com
Wed Mar 1 11:34:10 UTC 2017


Implement new repaint_begin and repaint_flush hooks inside
weston_backend, allowing backends to gang together repaints which
trigger at the same time.

Signed-off-by: Daniel Stone <daniels at collabora.com>
---
 libweston/compositor-drm.c      |  5 +++--
 libweston/compositor-fbdev.c    |  3 ++-
 libweston/compositor-headless.c |  3 ++-
 libweston/compositor-rdp.c      |  3 ++-
 libweston/compositor-wayland.c  |  6 ++++--
 libweston/compositor-x11.c      |  6 ++++--
 libweston/compositor.c          | 46 +++++++++++++++++++++++++++++------------
 libweston/compositor.h          | 38 ++++++++++++++++++++++++++++++++--
 8 files changed, 86 insertions(+), 24 deletions(-)

v2: Add repaint_cancel hook and documentation.

diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
index 2715a87..2776d31 100644
--- a/libweston/compositor-drm.c
+++ b/libweston/compositor-drm.c
@@ -718,7 +718,8 @@ drm_waitvblank_pipe(struct drm_output *output)
 
 static int
 drm_output_repaint(struct weston_output *output_base,
-		   pixman_region32_t *damage)
+		   pixman_region32_t *damage,
+		   void *repaint_data)
 {
 	struct drm_output *output = to_drm_output(output_base);
 	struct drm_backend *backend =
@@ -1317,7 +1318,7 @@ drm_output_set_cursor(struct drm_output *output)
 }
 
 static void
-drm_assign_planes(struct weston_output *output_base)
+drm_assign_planes(struct weston_output *output_base, void *repaint_data)
 {
 	struct drm_backend *b = to_drm_backend(output_base->compositor);
 	struct drm_output *output = to_drm_output(output_base);
diff --git a/libweston/compositor-fbdev.c b/libweston/compositor-fbdev.c
index 6f976d1..32d71e0 100644
--- a/libweston/compositor-fbdev.c
+++ b/libweston/compositor-fbdev.c
@@ -118,7 +118,8 @@ fbdev_output_start_repaint_loop(struct weston_output *output)
 }
 
 static int
-fbdev_output_repaint(struct weston_output *base, pixman_region32_t *damage)
+fbdev_output_repaint(struct weston_output *base, pixman_region32_t *damage,
+		     void *repaint_data)
 {
 	struct fbdev_output *output = to_fbdev_output(base);
 	struct weston_compositor *ec = output->base.compositor;
diff --git a/libweston/compositor-headless.c b/libweston/compositor-headless.c
index a1aec6d..9e42e7f 100644
--- a/libweston/compositor-headless.c
+++ b/libweston/compositor-headless.c
@@ -92,7 +92,8 @@ finish_frame_handler(void *data)
 
 static int
 headless_output_repaint(struct weston_output *output_base,
-		       pixman_region32_t *damage)
+		       pixman_region32_t *damage,
+		       void *repaint_data)
 {
 	struct headless_output *output = to_headless_output(output_base);
 	struct weston_compositor *ec = output->base.compositor;
diff --git a/libweston/compositor-rdp.c b/libweston/compositor-rdp.c
index d9668e8..091472b 100644
--- a/libweston/compositor-rdp.c
+++ b/libweston/compositor-rdp.c
@@ -355,7 +355,8 @@ rdp_output_start_repaint_loop(struct weston_output *output)
 }
 
 static int
-rdp_output_repaint(struct weston_output *output_base, pixman_region32_t *damage)
+rdp_output_repaint(struct weston_output *output_base, pixman_region32_t *damage,
+		   void *repaint_data)
 {
 	struct rdp_output *output = container_of(output_base, struct rdp_output, base);
 	struct weston_compositor *ec = output->base.compositor;
diff --git a/libweston/compositor-wayland.c b/libweston/compositor-wayland.c
index 9d35ef7..ebdbd13 100644
--- a/libweston/compositor-wayland.c
+++ b/libweston/compositor-wayland.c
@@ -488,7 +488,8 @@ wayland_output_start_repaint_loop(struct weston_output *output_base)
 #ifdef ENABLE_EGL
 static int
 wayland_output_repaint_gl(struct weston_output *output_base,
-			  pixman_region32_t *damage)
+			  pixman_region32_t *damage,
+			  void *repaint_data)
 {
 	struct wayland_output *output = to_wayland_output(output_base);
 	struct weston_compositor *ec = output->base.compositor;
@@ -595,7 +596,8 @@ wayland_shm_buffer_attach(struct wayland_shm_buffer *sb)
 
 static int
 wayland_output_repaint_pixman(struct weston_output *output_base,
-			      pixman_region32_t *damage)
+			      pixman_region32_t *damage,
+			      void *repaint_data)
 {
 	struct wayland_output *output = to_wayland_output(output_base);
 	struct wayland_backend *b =
diff --git a/libweston/compositor-x11.c b/libweston/compositor-x11.c
index f9cb461..02cdf3e 100644
--- a/libweston/compositor-x11.c
+++ b/libweston/compositor-x11.c
@@ -389,7 +389,8 @@ x11_output_start_repaint_loop(struct weston_output *output)
 
 static int
 x11_output_repaint_gl(struct weston_output *output_base,
-		      pixman_region32_t *damage)
+		      pixman_region32_t *damage,
+		      void *repaint_data)
 {
 	struct x11_output *output = to_x11_output(output_base);
 	struct weston_compositor *ec = output->base.compositor;
@@ -457,7 +458,8 @@ set_clip_for_output(struct weston_output *output_base, pixman_region32_t *region
 
 static int
 x11_output_repaint_shm(struct weston_output *output_base,
-		       pixman_region32_t *damage)
+		       pixman_region32_t *damage,
+		       void *repaint_data)
 {
 	struct x11_output *output = to_x11_output(output_base);
 	struct weston_compositor *ec = output->base.compositor;
diff --git a/libweston/compositor.c b/libweston/compositor.c
index 511f85a..ca9e251 100644
--- a/libweston/compositor.c
+++ b/libweston/compositor.c
@@ -2254,7 +2254,7 @@ weston_output_take_feedback_list(struct weston_output *output,
 }
 
 static int
-weston_output_repaint(struct weston_output *output)
+weston_output_repaint(struct weston_output *output, void *repaint_data)
 {
 	struct weston_compositor *ec = output->compositor;
 	struct weston_view *ev;
@@ -2273,7 +2273,7 @@ weston_output_repaint(struct weston_output *output)
 	weston_compositor_build_view_list(ec);
 
 	if (output->assign_planes && !output->disable_planes) {
-		output->assign_planes(output);
+		output->assign_planes(output, repaint_data);
 	} else {
 		wl_list_for_each(ev, &ec->view_list, link) {
 			weston_view_move_to_plane(ev, &ec->primary_plane);
@@ -2306,7 +2306,7 @@ weston_output_repaint(struct weston_output *output)
 	if (output->dirty)
 		weston_output_update_matrix(output);
 
-	r = output->repaint(output, &output_damage);
+	r = output->repaint(output, &output_damage, repaint_data);
 
 	pixman_region32_fini(&output_damage);
 
@@ -2338,21 +2338,21 @@ weston_output_schedule_repaint_reset(struct weston_output *output)
 	TL_POINT("core_repaint_exit_loop", TLP_OUTPUT(output), TLP_END);
 }
 
-static void
-weston_output_maybe_repaint(struct weston_output *output,
-			    struct timespec *now)
+static int
+weston_output_maybe_repaint(struct weston_output *output, struct timespec *now,
+			    void *repaint_data)
 {
 	struct weston_compositor *compositor = output->compositor;
-	int ret;
+	int ret = 0;
 	int64_t msec_to_repaint;
 
 	/* We're not ready yet; come back to make a decision later. */
 	if (output->repaint_status != REPAINT_SCHEDULED)
-		return;
+		return ret;
 
 	msec_to_repaint = timespec_sub_to_msec(&output->next_repaint, now);
 	if (msec_to_repaint > 1)
-		return;
+		return ret;
 
 	/* If we're sleeping, drop the repaint machinery entirely; we will
 	 * explicitly repaint all outputs when we come back. */
@@ -2370,15 +2370,16 @@ weston_output_maybe_repaint(struct weston_output *output,
 	 * something schedules a successful repaint later. As repainting may
 	 * take some time, re-read our clock as a courtesy to the next
 	 * output. */
-	ret = weston_output_repaint(output);
+	ret = weston_output_repaint(output, repaint_data);
 	weston_compositor_read_presentation_clock(compositor, now);
 	if (ret != 0)
 		goto err;
 
-	return;
+	return ret;
 
 err:
 	weston_output_schedule_repaint_reset(output);
+	return ret;
 }
 
 static void
@@ -2421,10 +2422,29 @@ output_repaint_timer_handler(void *data)
 	struct weston_compositor *compositor = data;
 	struct weston_output *output;
 	struct timespec now;
+	void *repaint_data = NULL;
+	int ret;
 
 	weston_compositor_read_presentation_clock(compositor, &now);
-	wl_list_for_each(output, &compositor->output_list, link)
-		weston_output_maybe_repaint(output, &now);
+
+	if (compositor->backend->repaint_begin)
+		repaint_data = compositor->backend->repaint_begin(compositor);
+
+	wl_list_for_each(output, &compositor->output_list, link) {
+		ret = weston_output_maybe_repaint(output, &now, repaint_data);
+		if (ret)
+			break;
+	}
+
+	if (ret == 0) {
+	    if (compositor->backend->repaint_flush)
+		    compositor->backend->repaint_flush(compositor,
+						       repaint_data);
+	} else {
+	    if (compositor->backend->repaint_cancel)
+		    compositor->backend->repaint_cancel(compositor,
+						        repaint_data);
+	}
 
 	output_repaint_timer_arm(compositor);
 
diff --git a/libweston/compositor.h b/libweston/compositor.h
index 93a02ae..3d44c40 100644
--- a/libweston/compositor.h
+++ b/libweston/compositor.h
@@ -211,9 +211,10 @@ struct weston_output {
 
 	void (*start_repaint_loop)(struct weston_output *output);
 	int (*repaint)(struct weston_output *output,
-			pixman_region32_t *damage);
+			pixman_region32_t *damage,
+			void *repaint_data);
 	void (*destroy)(struct weston_output *output);
-	void (*assign_planes)(struct weston_output *output);
+	void (*assign_planes)(struct weston_output *output, void *repaint_data);
 	int (*switch_mode)(struct weston_output *output, struct weston_mode *mode);
 
 	/* backlight values are on 0-255 range, where higher is brighter */
@@ -803,6 +804,39 @@ struct weston_backend_config {
 struct weston_backend {
 	void (*destroy)(struct weston_compositor *compositor);
 	void (*restore)(struct weston_compositor *compositor);
+
+	/** Begin a repaint sequence
+	 *
+	 * Provides the backend with explicit markers around repaint
+	 * sequences, which may allow the backend to aggregate state
+	 * application. This call will be bracketed by the repaint_flush (on
+	 * success), or repaint_cancel (when any output in the grouping fails
+	 * repaint).
+	 *
+	 * Returns an opaque pointer, which the backend may use as private
+	 * data referring to the repaint cycle.
+	 */
+	void * (*repaint_begin)(struct weston_compositor *compositor);
+
+	/** Cancel a repaint sequence
+	 *
+	 * Cancels a repaint sequence, when an error has occurred during
+	 * one output's repaint; see repaint_begin.
+	 *
+	 * @param repaint_data Data returned by repaint_begin
+	 */
+	void (*repaint_cancel)(struct weston_compositor *compositor,
+			       void *repaint_data);
+
+	/** Conclude a repaint sequence
+	 *
+	 * Called on successful completion of a repaint sequence; see
+	 * repaint_begin.
+	 *
+	 * @param repaint_data Data returned by repaint_begin
+	 */
+	void (*repaint_flush)(struct weston_compositor *compositor,
+			      void *repaint_data);
 };
 
 struct weston_desktop_xwayland;
-- 
2.9.3



More information about the wayland-devel mailing list