From b1f166d71e00d33eb43d9c02786476de2eef16f8 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Wed, 1 Mar 2017 11:34:10 +0000 Subject: [PATCH] Allow backends to group repaint flushes 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 Reviewed-by: Pekka Paalanen --- 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(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 72696d56..4cb27b1d 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -760,7 +760,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 = @@ -1375,7 +1376,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 6f976d17..32d71e0f 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 a1aec6d7..9e42e7f6 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 d9668e86..091472b0 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 9d35ef77..ebdbd13b 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 f9cb4612..02cdf3ea 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 527db208..fb647daa 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 @@ -2426,10 +2427,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 9e7ac99b..6070c774 100644 --- a/libweston/compositor.h +++ b/libweston/compositor.h @@ -212,9 +212,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 */ @@ -804,6 +805,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;