[PATCH weston 3/3] compositor-drm: Fix artifacts when scanning out a client buffer
Kristian Høgsberg
krh at bitplanet.net
Wed Nov 21 11:39:07 PST 2012
On Wed, Nov 21, 2012 at 8:11 AM, Ander Conselvan de Oliveira
<ander.conselvan.de.oliveira at intel.com> wrote:
> Consider the following scenario: a fullscreen surface is composited for
> a few frames and suddenly it is moved to a scan out plane. (This could
> happen for instance if it used a big cursor and later switched to a
> cursor that fits in the hw cursor overlay.) If that surface is resized
> during one frame such that it can no longer be scanned out, the
> following frames won't be repainted properly.
>
> The reason for this is that the renderer's repaint function is not
> called if a client buffer is scanned out. When the surface moves to the
> scan out plane, the primary plane is damaged but that damage never hits
> the renderer. When we switch back to compositing, the output back
> buffers are dirty. One of them is updated because of the damage stored
> on the gl renderer per buffer damage for the last composited frame, but
> the other buffer is not redraw.
Ah, I see. I think the problem instead is that we clear
primary_plane->damage unconditionally in weston_output_repaint, even
if we don't actually paint that damage. If we move the clearing to
the output repaint vfunc, and only call it when we render, I think
that will solve the problem.
Kristian
> This patch fix this bug by storing all the damage coming from the
> compositor when scanning out a client buffer and feeding that back to
> the renderer once it switches back to compositing.
> ---
> src/compositor-drm.c | 22 +++++++++++++++++++---
> 1 file changed, 19 insertions(+), 3 deletions(-)
>
> diff --git a/src/compositor-drm.c b/src/compositor-drm.c
> index 142faa5..2be903c 100644
> --- a/src/compositor-drm.c
> +++ b/src/compositor-drm.c
> @@ -142,6 +142,7 @@ struct drm_output {
> int current_cursor;
> struct drm_fb *current, *next;
> struct backlight *backlight;
> + pixman_region32_t pending_damage;
> };
>
> /*
> @@ -382,10 +383,21 @@ drm_output_repaint(struct weston_output *output_base,
> struct drm_mode *mode;
> int ret = 0;
>
> - if (!output->next)
> + if (output->next) {
> + /* Since the renderer is not going to be called, save this
> + * damage for later */
> + pixman_region32_union(&output->pending_damage,
> + &output->pending_damage, damage);
> + } else {
> + pixman_region32_union(damage,
> + damage, &output->pending_damage);
> + pixman_region32_fini(&output->pending_damage);
> + pixman_region32_init(&output->pending_damage);
> +
> drm_output_render(output, damage);
> - if (!output->next)
> - return;
> + if (!output->next)
> + return;
> + }
>
> mode = container_of(output->base.current, struct drm_mode, base);
> if (!output->current) {
> @@ -837,6 +849,8 @@ drm_output_destroy(struct weston_output *output_base)
>
> gbm_surface_destroy(output->surface);
>
> + pixman_region32_fini(&output->pending_damage);
> +
> weston_plane_release(&output->fb_plane);
> weston_plane_release(&output->cursor_plane);
>
> @@ -1404,6 +1418,8 @@ create_output_for_connector(struct drm_compositor *ec,
> weston_plane_init(&output->cursor_plane, 0, 0);
> weston_plane_init(&output->fb_plane, 0, 0);
>
> + pixman_region32_init(&output->pending_damage);
> +
> weston_log("Output %s, (connector %d, crtc %d)\n",
> output->name, output->connector_id, output->crtc_id);
> wl_list_for_each(m, &output->base.mode_list, link)
> --
> 1.7.10.4
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
More information about the wayland-devel
mailing list