From acf50c3d96a5ab7b393a064e10b6e4affbd7236f Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Mon, 23 Apr 2018 11:44:56 +0200 Subject: [PATCH] pixman,drm: do not composite previous damage Pixman-renderer uses a single internal shadow buffer. It is enough to composite the current damage into shadow, but the copy to hw buffer needs to include the previous damage because of double-buffering in DRM-backend. This patch lets pixman-renderer do exactly that without compositing also the previous damage on DRM-renderer. Arguably weston_output should not have field previous_damage to begin with, because it implies double-buffering, which e.g. EGL does not guarantee. It would be better for each backend explicitly always provide any extra damage that should be copied to hw. Signed-off-by: Pekka Paalanen Signed-off-by: Fabien Lahoudere Reviewed-by: Ian Ray --- libweston/compositor-drm.c | 16 ++++------------ libweston/pixman-renderer.c | 35 ++++++++++++++++++++++++++++++----- libweston/pixman-renderer.h | 7 ++++++- 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c index 287431eb..52b5dd70 100644 --- a/libweston/compositor-drm.c +++ b/libweston/compositor-drm.c @@ -1673,25 +1673,17 @@ drm_output_render_pixman(struct drm_output_state *state, { struct drm_output *output = state->output; struct weston_compositor *ec = output->base.compositor; - pixman_region32_t total_damage, previous_damage; - - pixman_region32_init(&total_damage); - pixman_region32_init(&previous_damage); - - pixman_region32_copy(&previous_damage, damage); - - pixman_region32_union(&total_damage, damage, &output->previous_damage); - pixman_region32_copy(&output->previous_damage, &previous_damage); output->current_image ^= 1; pixman_renderer_output_set_buffer(&output->base, output->image[output->current_image]); + pixman_renderer_output_set_hw_extra_damage(&output->base, + &output->previous_damage); - ec->renderer->repaint_output(&output->base, &total_damage); + ec->renderer->repaint_output(&output->base, damage); - pixman_region32_fini(&total_damage); - pixman_region32_fini(&previous_damage); + pixman_region32_copy(&output->previous_damage, damage); return drm_fb_ref(output->dumb[output->current_image]); } diff --git a/libweston/pixman-renderer.c b/libweston/pixman-renderer.c index f7366cf6..cf43b15d 100644 --- a/libweston/pixman-renderer.c +++ b/libweston/pixman-renderer.c @@ -41,6 +41,7 @@ struct pixman_output_state { void *shadow_buffer; pixman_image_t *shadow_image; pixman_image_t *hw_buffer; + pixman_region32_t *hw_extra_damage; }; struct pixman_surface_state { @@ -555,15 +556,29 @@ copy_to_hw_buffer(struct weston_output *output, pixman_region32_t *region) static void pixman_renderer_repaint_output(struct weston_output *output, - pixman_region32_t *output_damage) + pixman_region32_t *output_damage) { struct pixman_output_state *po = get_output_state(output); + pixman_region32_t hw_damage; - if (!po->hw_buffer) - return; + if (!po->hw_buffer) { + po->hw_extra_damage = NULL; + return; + } + + pixman_region32_init(&hw_damage); + if (po->hw_extra_damage) { + pixman_region32_union(&hw_damage, + po->hw_extra_damage, output_damage); + po->hw_extra_damage = NULL; + } else { + pixman_region32_copy(&hw_damage, output_damage); + } repaint_surfaces(output, output_damage); - copy_to_hw_buffer(output, output_damage); + + copy_to_hw_buffer(output, &hw_damage); + pixman_region32_fini(&hw_damage); pixman_region32_copy(&output->previous_damage, output_damage); wl_signal_emit(&output->frame_signal, output); @@ -862,7 +877,8 @@ pixman_renderer_init(struct weston_compositor *ec) } WL_EXPORT void -pixman_renderer_output_set_buffer(struct weston_output *output, pixman_image_t *buffer) +pixman_renderer_output_set_buffer(struct weston_output *output, + pixman_image_t *buffer) { struct pixman_output_state *po = get_output_state(output); @@ -876,6 +892,15 @@ pixman_renderer_output_set_buffer(struct weston_output *output, pixman_image_t * } } +WL_EXPORT void +pixman_renderer_output_set_hw_extra_damage(struct weston_output *output, + pixman_region32_t *extra_damage) +{ + struct pixman_output_state *po = get_output_state(output); + + po->hw_extra_damage = extra_damage; +} + WL_EXPORT int pixman_renderer_output_create(struct weston_output *output) { diff --git a/libweston/pixman-renderer.h b/libweston/pixman-renderer.h index 1b42f14f..f19e1477 100644 --- a/libweston/pixman-renderer.h +++ b/libweston/pixman-renderer.h @@ -34,7 +34,12 @@ int pixman_renderer_output_create(struct weston_output *output); void -pixman_renderer_output_set_buffer(struct weston_output *output, pixman_image_t *buffer); +pixman_renderer_output_set_buffer(struct weston_output *output, + pixman_image_t *buffer); + +void +pixman_renderer_output_set_hw_extra_damage(struct weston_output *output, + pixman_region32_t *extra_damage); void pixman_renderer_output_destroy(struct weston_output *output);