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
