libweston: Let renderers manage renderbuffers' damage

Move the responsibility for damaging the entire area of new
renderbuffers from backends to renderers.

There's one little drawback: VNC damage logging can't log the
accumulated renderbuffer damage anymore, but I guess this should
somehow be done as an option in the renderers.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
This commit is contained in:
Loïc Molinari 2024-07-31 18:29:35 +02:00
parent c01a1f7c64
commit 1619a4a1e5
7 changed files with 36 additions and 56 deletions

View file

@ -1630,12 +1630,6 @@ drm_output_init_pixman(struct drm_output *output, struct drm_backend *b)
output->dumb[i]->strides[0]);
if (!output->renderbuffer[i])
goto err;
pixman_region32_init_rect(&output->renderbuffer[i]->damage,
output->base.pos.c.x,
output->base.pos.c.y,
output->base.width,
output->base.height);
}
weston_log("DRM: output %s %s shadow framebuffer.\n", output->base.name,

View file

@ -384,9 +384,6 @@ rdp_output_set_mode(struct weston_output *base, struct weston_mode *mode)
default:
unreachable("cannot have auto renderer at runtime");
}
pixman_image_composite32(PIXMAN_OP_SRC, rdpOutput->shadow_surface,
0, new_image, 0, 0, 0, 0, 0, 0,
mode->width, mode->height);
weston_renderbuffer_unref(rdpOutput->renderbuffer);
rdpOutput->renderbuffer = new_renderbuffer;
pixman_image_unref(rdpOutput->shadow_surface);

View file

@ -653,8 +653,7 @@ vnc_log_scope_print_region(struct weston_log_scope *log, pixman_region32_t *regi
}
static void
vnc_log_damage(struct vnc_backend *backend, pixman_region32_t *buffer_damage,
pixman_region32_t *update_damage)
vnc_log_damage(struct vnc_backend *backend, pixman_region32_t *damage)
{
char timestr[128];
@ -663,12 +662,8 @@ vnc_log_damage(struct vnc_backend *backend, pixman_region32_t *buffer_damage,
weston_log_scope_timestamp(backend->debug, timestr, sizeof timestr);
weston_log_scope_printf(backend->debug, "%s buffer damage:", timestr);
vnc_log_scope_print_region(backend->debug, buffer_damage);
weston_log_scope_printf(backend->debug, "\n");
weston_log_scope_printf(backend->debug, "%s update damage:", timestr);
vnc_log_scope_print_region(backend->debug, update_damage);
weston_log_scope_printf(backend->debug, "%s damage:", timestr);
vnc_log_scope_print_region(backend->debug, damage);
weston_log_scope_printf(backend->debug, "\n\n");
}
@ -719,15 +714,11 @@ vnc_update_buffer(struct nvnc_display *display, struct pixman_region32 *damage)
unreachable("cannot have auto renderer at runtime");
}
/* This is a new buffer, so the whole surface is damaged. */
pixman_region32_copy(&renderbuffer->damage,
&output->base.region);
nvnc_set_userdata(fb, renderbuffer,
(nvnc_cleanup_fn)weston_renderbuffer_unref);
}
vnc_log_damage(backend, &renderbuffer->damage, damage);
vnc_log_damage(backend, damage);
ec->renderer->repaint_output(&output->base, damage, renderbuffer);

View file

@ -395,15 +395,12 @@ wayland_output_get_shm_buffer(struct wayland_output *output)
pixman = renderer->pixman;
/* Address only the interior, excluding output decorations */
if (renderer->type == WESTON_RENDERER_PIXMAN) {
if (renderer->type == WESTON_RENDERER_PIXMAN)
sb->renderbuffer =
pixman->create_image_from_ptr(&output->base, pfmt,
area.width, area.height,
(uint32_t *)(data + area.y * stride) + area.x,
stride);
pixman_region32_copy(&sb->renderbuffer->damage,
&output->base.region);
}
return sb;
}

View file

@ -47,7 +47,6 @@
/* compositor <-> renderer interface */
struct weston_renderbuffer {
pixman_region32_t damage;
int refcount;
void (*destroy)(struct weston_renderbuffer *renderbuffer);

View file

@ -66,6 +66,7 @@ struct pixman_surface_state {
struct pixman_renderbuffer {
struct weston_renderbuffer base;
pixman_region32_t damage;
pixman_image_t *image;
struct wl_list link;
};
@ -651,6 +652,11 @@ pixman_renderer_repaint_output(struct weston_output *output,
assert(renderbuffer);
/* Accumulate damage in all renderbuffers */
wl_list_for_each(rb, &po->renderbuffer_list, link) {
pixman_region32_union(&rb->damage, &rb->damage, output_damage);
}
rb = to_pixman_renderbuffer(renderbuffer);
pixman_renderer_output_set_buffer(output, rb->image);
@ -661,26 +667,19 @@ pixman_renderer_repaint_output(struct weston_output *output,
if (!po->hw_buffer)
return;
/* Accumulate damage in all renderbuffers */
wl_list_for_each(rb, &po->renderbuffer_list, link) {
pixman_region32_union(&rb->base.damage,
&rb->base.damage,
output_damage);
}
if (po->shadow_image) {
repaint_surfaces(output, output_damage);
pixman_renderer_do_capture_tasks(output,
WESTON_OUTPUT_CAPTURE_SOURCE_BLENDING,
po->shadow_image, po->shadow_format);
copy_to_hw_buffer(output, &renderbuffer->damage);
copy_to_hw_buffer(output, &rb->damage);
} else {
repaint_surfaces(output, &renderbuffer->damage);
repaint_surfaces(output, &rb->damage);
}
pixman_renderer_do_capture_tasks(output,
WESTON_OUTPUT_CAPTURE_SOURCE_FRAMEBUFFER,
po->hw_buffer, po->hw_format);
pixman_region32_clear(&renderbuffer->damage);
pixman_region32_clear(&rb->damage);
wl_signal_emit(&output->frame_signal, output_damage);
@ -1177,7 +1176,8 @@ pixman_renderer_create_image_from_ptr(struct weston_output *output,
return NULL;
}
pixman_region32_init(&renderbuffer->base.damage);
pixman_region32_init(&renderbuffer->damage);
pixman_region32_copy(&renderbuffer->damage, &output->region);
renderbuffer->base.refcount = 2;
renderbuffer->base.destroy = pixman_renderer_renderbuffer_destroy;
wl_list_insert(&po->renderbuffer_list, &renderbuffer->link);
@ -1205,7 +1205,8 @@ pixman_renderer_create_image(struct weston_output *output,
return NULL;
}
pixman_region32_init(&renderbuffer->base.damage);
pixman_region32_init(&renderbuffer->damage);
pixman_region32_copy(&renderbuffer->damage, &output->region);
renderbuffer->base.refcount = 2;
renderbuffer->base.destroy = pixman_renderer_renderbuffer_destroy;
wl_list_insert(&po->renderbuffer_list, &renderbuffer->link);
@ -1219,7 +1220,7 @@ pixman_renderer_renderbuffer_destroy(struct weston_renderbuffer *renderbuffer)
struct pixman_renderbuffer *rb = to_pixman_renderbuffer(renderbuffer);
pixman_image_unref(rb->image);
pixman_region32_fini(&rb->base.damage);
pixman_region32_fini(&rb->damage);
free(rb);
}

View file

@ -104,6 +104,7 @@ struct gl_fbo_texture {
struct gl_renderbuffer {
struct weston_renderbuffer base;
pixman_region32_t damage;
enum gl_border_status border_damage;
/* The fbo value zero represents the default surface framebuffer. */
GLuint fbo;
@ -695,7 +696,7 @@ gl_renderer_renderbuffer_destroy(struct weston_renderbuffer *renderbuffer)
glDeleteFramebuffers(1, &rb->fbo);
glDeleteRenderbuffers(1, &rb->rb);
pixman_region32_fini(&rb->base.damage);
pixman_region32_fini(&rb->damage);
free(rb);
}
@ -709,8 +710,8 @@ gl_renderer_create_dummy_renderbuffer(struct weston_output *output)
renderbuffer->fbo = 0;
pixman_region32_init(&renderbuffer->base.damage);
pixman_region32_copy(&renderbuffer->base.damage, &output->region);
pixman_region32_init(&renderbuffer->damage);
pixman_region32_copy(&renderbuffer->damage, &output->region);
renderbuffer->border_damage = BORDER_ALL_DIRTY;
/*
* A single reference is kept on the renderbuffer_list,
@ -775,7 +776,8 @@ gl_renderer_create_fbo(struct weston_output *output,
renderbuffer->pixels = pixels;
pixman_region32_init(&renderbuffer->base.damage);
pixman_region32_init(&renderbuffer->damage);
pixman_region32_copy(&renderbuffer->damage, &output->region);
/*
* One reference is kept on the renderbuffer_list,
* the other is returned to the calling backend.
@ -2153,7 +2155,7 @@ output_get_dummy_renderbuffer(struct weston_output *output)
BUFFER_DAMAGE_COUNT : 1;
if ((buffer_age == 0 || buffer_age - 1 > BUFFER_DAMAGE_COUNT) &&
count >= max_buffers) {
pixman_region32_copy(&oldest_rb->base.damage, &output->region);
pixman_region32_copy(&oldest_rb->damage, &output->region);
oldest_rb->border_damage = BORDER_ALL_DIRTY;
oldest_rb->age = 0;
return oldest_rb;
@ -2355,9 +2357,7 @@ gl_renderer_repaint_output(struct weston_output *output,
/* Accumulate damage in all renderbuffers */
wl_list_for_each(rb, &go->renderbuffer_list, link) {
pixman_region32_union(&rb->base.damage,
&rb->base.damage,
output_damage);
pixman_region32_union(&rb->damage, &rb->damage, output_damage);
rb->border_damage |= go->border_status;
}
@ -2410,7 +2410,7 @@ gl_renderer_repaint_output(struct weston_output *output,
if (gr->debug_clear) {
pixman_region32_t undamaged;
pixman_region32_t *damaged =
shadow_exists(go) ? output_damage : &rb->base.damage;
shadow_exists(go) ? output_damage : &rb->damage;
int debug_mode = gr->debug_mode;
pixman_region32_init(&undamaged);
@ -2429,7 +2429,7 @@ gl_renderer_repaint_output(struct weston_output *output,
/* For partial_update, we need to pass the region which has
* changed since we last rendered into this specific buffer. */
pixman_region_to_egl(output, &rb->base.damage,
pixman_region_to_egl(output, &rb->damage,
&egl_rects, &n_egl_rects);
gr->set_damage_region(gr->egl_display, go->egl_surface,
egl_rects, n_egl_rects);
@ -2447,9 +2447,9 @@ gl_renderer_repaint_output(struct weston_output *output,
glViewport(go->area.x, area_y,
go->area.width, go->area.height);
blit_shadow_to_output(output, gr->debug_clear ?
&output->region : &rb->base.damage);
&output->region : &rb->damage);
} else {
repaint_views(output, &rb->base.damage);
repaint_views(output, &rb->damage);
}
draw_output_borders(output, rb->border_damage);
@ -2518,7 +2518,7 @@ gl_renderer_repaint_output(struct weston_output *output,
};
extents = weston_matrix_transform_rect(&output->matrix,
rb->base.damage.extents);
rb->damage.extents);
if (gr->debug_clear) {
rect.y = go->area.y;
@ -2543,7 +2543,7 @@ gl_renderer_repaint_output(struct weston_output *output,
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
}
pixman_region32_clear(&rb->base.damage);
pixman_region32_clear(&rb->damage);
gl_renderer_garbage_collect_programs(gr);
}
@ -4208,7 +4208,7 @@ gl_renderer_dmabuf_renderbuffer_destroy(struct weston_renderbuffer *renderbuffer
glDeleteFramebuffers(1, &gl_renderbuffer->fbo);
glDeleteRenderbuffers(1, &gl_renderbuffer->rb);
pixman_region32_fini(&gl_renderbuffer->base.damage);
pixman_region32_fini(&gl_renderbuffer->damage);
gr->destroy_image(gr->egl_display, dmabuf_renderbuffer->image);
@ -4272,7 +4272,8 @@ gl_renderer_create_renderbuffer_dmabuf(struct weston_output *output,
rb->gr = gr;
rb->dmabuf = dmabuf;
pixman_region32_init(&rb->base.base.damage);
pixman_region32_init(&renderbuffer->damage);
pixman_region32_copy(&renderbuffer->damage, &output->region);
/*
* One reference is kept on the renderbuffer_list,
* the other is returned to the calling backend.