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 <daniels@collabora.com>
Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
dev
Daniel Stone 8 years ago committed by Pekka Paalanen
parent 6847b858a3
commit b1f166d71e
  1. 5
      libweston/compositor-drm.c
  2. 3
      libweston/compositor-fbdev.c
  3. 3
      libweston/compositor-headless.c
  4. 3
      libweston/compositor-rdp.c
  5. 6
      libweston/compositor-wayland.c
  6. 6
      libweston/compositor-x11.c
  7. 46
      libweston/compositor.c
  8. 38
      libweston/compositor.h

@ -760,7 +760,8 @@ drm_waitvblank_pipe(struct drm_output *output)
static int static int
drm_output_repaint(struct weston_output *output_base, 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_output *output = to_drm_output(output_base);
struct drm_backend *backend = struct drm_backend *backend =
@ -1375,7 +1376,7 @@ drm_output_set_cursor(struct drm_output *output)
} }
static void 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_backend *b = to_drm_backend(output_base->compositor);
struct drm_output *output = to_drm_output(output_base); struct drm_output *output = to_drm_output(output_base);

@ -118,7 +118,8 @@ fbdev_output_start_repaint_loop(struct weston_output *output)
} }
static int 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 fbdev_output *output = to_fbdev_output(base);
struct weston_compositor *ec = output->base.compositor; struct weston_compositor *ec = output->base.compositor;

@ -92,7 +92,8 @@ finish_frame_handler(void *data)
static int static int
headless_output_repaint(struct weston_output *output_base, 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 headless_output *output = to_headless_output(output_base);
struct weston_compositor *ec = output->base.compositor; struct weston_compositor *ec = output->base.compositor;

@ -355,7 +355,8 @@ rdp_output_start_repaint_loop(struct weston_output *output)
} }
static int 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 rdp_output *output = container_of(output_base, struct rdp_output, base);
struct weston_compositor *ec = output->base.compositor; struct weston_compositor *ec = output->base.compositor;

@ -488,7 +488,8 @@ wayland_output_start_repaint_loop(struct weston_output *output_base)
#ifdef ENABLE_EGL #ifdef ENABLE_EGL
static int static int
wayland_output_repaint_gl(struct weston_output *output_base, 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 wayland_output *output = to_wayland_output(output_base);
struct weston_compositor *ec = output->base.compositor; struct weston_compositor *ec = output->base.compositor;
@ -595,7 +596,8 @@ wayland_shm_buffer_attach(struct wayland_shm_buffer *sb)
static int static int
wayland_output_repaint_pixman(struct weston_output *output_base, 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_output *output = to_wayland_output(output_base);
struct wayland_backend *b = struct wayland_backend *b =

@ -389,7 +389,8 @@ x11_output_start_repaint_loop(struct weston_output *output)
static int static int
x11_output_repaint_gl(struct weston_output *output_base, 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 x11_output *output = to_x11_output(output_base);
struct weston_compositor *ec = output->base.compositor; 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 static int
x11_output_repaint_shm(struct weston_output *output_base, 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 x11_output *output = to_x11_output(output_base);
struct weston_compositor *ec = output->base.compositor; struct weston_compositor *ec = output->base.compositor;

@ -2254,7 +2254,7 @@ weston_output_take_feedback_list(struct weston_output *output,
} }
static int 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_compositor *ec = output->compositor;
struct weston_view *ev; struct weston_view *ev;
@ -2273,7 +2273,7 @@ weston_output_repaint(struct weston_output *output)
weston_compositor_build_view_list(ec); weston_compositor_build_view_list(ec);
if (output->assign_planes && !output->disable_planes) { if (output->assign_planes && !output->disable_planes) {
output->assign_planes(output); output->assign_planes(output, repaint_data);
} else { } else {
wl_list_for_each(ev, &ec->view_list, link) { wl_list_for_each(ev, &ec->view_list, link) {
weston_view_move_to_plane(ev, &ec->primary_plane); weston_view_move_to_plane(ev, &ec->primary_plane);
@ -2306,7 +2306,7 @@ weston_output_repaint(struct weston_output *output)
if (output->dirty) if (output->dirty)
weston_output_update_matrix(output); weston_output_update_matrix(output);
r = output->repaint(output, &output_damage); r = output->repaint(output, &output_damage, repaint_data);
pixman_region32_fini(&output_damage); 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); TL_POINT("core_repaint_exit_loop", TLP_OUTPUT(output), TLP_END);
} }
static void static int
weston_output_maybe_repaint(struct weston_output *output, weston_output_maybe_repaint(struct weston_output *output, struct timespec *now,
struct timespec *now) void *repaint_data)
{ {
struct weston_compositor *compositor = output->compositor; struct weston_compositor *compositor = output->compositor;
int ret; int ret = 0;
int64_t msec_to_repaint; int64_t msec_to_repaint;
/* We're not ready yet; come back to make a decision later. */ /* We're not ready yet; come back to make a decision later. */
if (output->repaint_status != REPAINT_SCHEDULED) if (output->repaint_status != REPAINT_SCHEDULED)
return; return ret;
msec_to_repaint = timespec_sub_to_msec(&output->next_repaint, now); msec_to_repaint = timespec_sub_to_msec(&output->next_repaint, now);
if (msec_to_repaint > 1) if (msec_to_repaint > 1)
return; return ret;
/* If we're sleeping, drop the repaint machinery entirely; we will /* If we're sleeping, drop the repaint machinery entirely; we will
* explicitly repaint all outputs when we come back. */ * 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 * something schedules a successful repaint later. As repainting may
* take some time, re-read our clock as a courtesy to the next * take some time, re-read our clock as a courtesy to the next
* output. */ * output. */
ret = weston_output_repaint(output); ret = weston_output_repaint(output, repaint_data);
weston_compositor_read_presentation_clock(compositor, now); weston_compositor_read_presentation_clock(compositor, now);
if (ret != 0) if (ret != 0)
goto err; goto err;
return; return ret;
err: err:
weston_output_schedule_repaint_reset(output); weston_output_schedule_repaint_reset(output);
return ret;
} }
static void static void
@ -2426,10 +2427,29 @@ output_repaint_timer_handler(void *data)
struct weston_compositor *compositor = data; struct weston_compositor *compositor = data;
struct weston_output *output; struct weston_output *output;
struct timespec now; struct timespec now;
void *repaint_data = NULL;
int ret;
weston_compositor_read_presentation_clock(compositor, &now); 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); output_repaint_timer_arm(compositor);

@ -212,9 +212,10 @@ struct weston_output {
void (*start_repaint_loop)(struct weston_output *output); void (*start_repaint_loop)(struct weston_output *output);
int (*repaint)(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 (*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); int (*switch_mode)(struct weston_output *output, struct weston_mode *mode);
/* backlight values are on 0-255 range, where higher is brighter */ /* backlight values are on 0-255 range, where higher is brighter */
@ -804,6 +805,39 @@ struct weston_backend_config {
struct weston_backend { struct weston_backend {
void (*destroy)(struct weston_compositor *compositor); void (*destroy)(struct weston_compositor *compositor);
void (*restore)(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; struct weston_desktop_xwayland;

Loading…
Cancel
Save