Looks like I need to autoNAK and try again.

The problem occurs when the *previous* frame is capable of overflowing
damage (eg: bilinear filtering was used), and can't be solved completely
based purely on current state.

On 02/12/15 01:46 PM, Derek Foreman wrote:
> When we zoom or scale an output it's possible for a single buffer
> pixel to be stretched over multiple output pixels.
> 
> When this happens, if a client is sending exact damage rectangles
> we can end up with incomplete updates - the client doesn't know
> that the previous frame resulted in some pixel bleeding, and
> can't reasonably get damage right.
> 
> To fix this, we'll dilate the damage region by a little bit all
> around.  We may be dilating a little too much, but a pixel or two
> too far is better than being too small.
> 
> The problem is easily seen with weston_simple_damage when the
> output is zoomed, or when running with a lower buffer scale
> than the output scale.  The moving circle will leave trails.
> 
> Signed-off-by: Derek Foreman <[email protected]>
> ---
>  src/gl-renderer.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++------
>  1 file changed, 47 insertions(+), 6 deletions(-)
> 
> diff --git a/src/gl-renderer.c b/src/gl-renderer.c
> index ae72f32..eb18931 100644
> --- a/src/gl-renderer.c
> +++ b/src/gl-renderer.c
> @@ -1006,6 +1006,33 @@ output_rotate_damage(struct weston_output *output,
>       go->border_damage[go->buffer_damage_index] = border_status;
>  }
>  
> +static void
> +region_dilate(pixman_region32_t *region, double size)
> +{
> +        pixman_box32_t *src_rects, *dest_rects;
> +        int nrects, i;
> +
> +        src_rects = pixman_region32_rectangles(region, &nrects);
> +        dest_rects = malloc(nrects * sizeof(*dest_rects));
> +        if (!dest_rects)
> +                return;
> +
> +        for (i = 0; i < nrects; i++) {
> +             dest_rects[i].x1 = src_rects[i].x1 - size;
> +             if (dest_rects[i].x1 < 0)
> +                     dest_rects[i].x1 = 0;
> +             dest_rects[i].x2 = src_rects[i].x2 + size;
> +             dest_rects[i].y1 = src_rects[i].y1 - size;
> +             if (dest_rects[i].y1 < 0)
> +                     dest_rects[i].y1 = 0;
> +             dest_rects[i].y2 = src_rects[i].y2 + size;
> +     }
> +
> +        pixman_region32_clear(region);
> +        pixman_region32_init_rects(region, dest_rects, nrects);
> +        free(dest_rects);
> +}
> +
>  /* NOTE: We now allow falling back to ARGB gl visuals when XRGB is
>   * unavailable, so we're assuming the background has no transparency
>   * and that everything with a blend, like drop shadows, will have something
> @@ -1016,7 +1043,7 @@ output_rotate_damage(struct weston_output *output,
>   */
>  static void
>  gl_renderer_repaint_output(struct weston_output *output,
> -                           pixman_region32_t *output_damage)
> +                           pixman_region32_t *output_damage_in)
>  {
>       struct gl_output_state *go = get_output_state(output);
>       struct weston_compositor *compositor = output->compositor;
> @@ -1028,12 +1055,25 @@ gl_renderer_repaint_output(struct weston_output 
> *output,
>       EGLint *egl_damage, *d;
>       pixman_box32_t *rects;
>  #endif
> +     pixman_region32_t output_damage;
>       pixman_region32_t buffer_damage, total_damage;
>       enum gl_border_status border_damage = BORDER_STATUS_CLEAN;
>  
>       if (use_output(output) < 0)
>               return;
>  
> +     pixman_region32_init(&output_damage);
> +     pixman_region32_copy(&output_damage, output_damage_in);
> +
> +     /* When the output is scaled or zoomed a single buffer
> +      * pixel may be spread across multiple output pixels.
> +      * Therefore, if damage is exact in buffer space there may
> +      * be bleeding into neighbouring output pixels.  We dilate
> +      * the damage region to compensate.
> +      */
> +     if (output->zoom.active || output->current_scale > 1)
> +             region_dilate(&output_damage, output->current_scale);
> +
>       /* Calculate the viewport */
>       glViewport(go->borders[GL_RENDERER_BORDER_LEFT].width,
>                  go->borders[GL_RENDERER_BORDER_BOTTOM].height,
> @@ -1056,7 +1096,7 @@ gl_renderer_repaint_output(struct weston_output *output,
>               pixman_region32_t undamaged;
>               pixman_region32_init(&undamaged);
>               pixman_region32_subtract(&undamaged, &output->region,
> -                                      output_damage);
> +                                      &output_damage);
>               gr->fan_debug = 0;
>               repaint_views(output, &undamaged);
>               gr->fan_debug = 1;
> @@ -1067,9 +1107,9 @@ gl_renderer_repaint_output(struct weston_output *output,
>       pixman_region32_init(&buffer_damage);
>  
>       output_get_damage(output, &buffer_damage, &border_damage);
> -     output_rotate_damage(output, output_damage, go->border_status);
> +     output_rotate_damage(output, &output_damage, go->border_status);
>  
> -     pixman_region32_union(&total_damage, &buffer_damage, output_damage);
> +     pixman_region32_union(&total_damage, &buffer_damage, &output_damage);
>       border_damage |= go->border_status;
>  
>       repaint_views(output, &total_damage);
> @@ -1079,7 +1119,7 @@ gl_renderer_repaint_output(struct weston_output *output,
>  
>       draw_output_borders(output, border_damage);
>  
> -     pixman_region32_copy(&output->previous_damage, output_damage);
> +     pixman_region32_copy(&output->previous_damage, &output_damage);
>       wl_signal_emit(&output->frame_signal, output);
>  
>  #ifdef EGL_EXT_swap_buffers_with_damage
> @@ -1088,7 +1128,7 @@ gl_renderer_repaint_output(struct weston_output *output,
>               weston_transformed_region(output->width, output->height,
>                                         output->transform,
>                                         output->current_scale,
> -                                       output_damage, &buffer_damage);
> +                                       &output_damage, &buffer_damage);
>  
>               if (output_has_borders(output)) {
>                       pixman_region32_translate(&buffer_damage,
> @@ -1131,6 +1171,7 @@ gl_renderer_repaint_output(struct weston_output *output,
>       }
>  
>       go->border_status = BORDER_STATUS_CLEAN;
> +     pixman_region32_fini(&output_damage);
>  }
>  
>  static int
> 

_______________________________________________
wayland-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to