From 4d96635a3f18dd93c23c0c25769af1a3b3cd0d15 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Wed, 11 Jan 2023 23:34:39 +0100 Subject: [PATCH] pixman-renderer: track damage in weston_renderbuffer Add a damage region to struct weston_renderbuffer and use it to replace the previous_damage tracking in the drm backend. Keep renderbuffers on a list in struct pixman_output_state and use it to accumulate damage on all renderbuffers during repaint_output. Now renderbuffers have to be created when pixman output state already exists. Reorder renderer output state and renderbuffer creation accordingly. With this, pixman_renderer_output_set_hw_extra_damage() can be removed. This can not yet replace the external damage tracking in the VNC backend, which needsto know the accumulated damage that is not returned from repaint_output. Signed-off-by: Philipp Zabel --- libweston/backend-drm/drm-internal.h | 1 - libweston/backend-drm/drm.c | 25 ++++++------- libweston/backend-headless/headless.c | 10 +++--- libweston/backend-rdp/rdp.c | 10 +++--- libweston/libweston-internal.h | 2 ++ libweston/pixman-renderer.c | 52 ++++++++++++++------------- libweston/pixman-renderer.h | 4 --- 7 files changed, 50 insertions(+), 54 deletions(-) diff --git a/libweston/backend-drm/drm-internal.h b/libweston/backend-drm/drm-internal.h index 0c339349..e101346b 100644 --- a/libweston/backend-drm/drm-internal.h +++ b/libweston/backend-drm/drm-internal.h @@ -595,7 +595,6 @@ struct drm_output { struct drm_fb *dumb[2]; struct weston_renderbuffer *renderbuffer[2]; int current_image; - pixman_region32_t previous_damage; struct vaapi_recorder *recorder; struct wl_listener recorder_frame_listener; diff --git a/libweston/backend-drm/drm.c b/libweston/backend-drm/drm.c index 3060e73d..b58d1fef 100644 --- a/libweston/backend-drm/drm.c +++ b/libweston/backend-drm/drm.c @@ -343,14 +343,9 @@ drm_output_render_pixman(struct drm_output_state *state, output->current_image ^= 1; - pixman_renderer_output_set_hw_extra_damage(&output->base, - &output->previous_damage); - ec->renderer->repaint_output(&output->base, damage, output->renderbuffer[output->current_image]); - pixman_region32_copy(&output->previous_damage, damage); - return drm_fb_ref(output->dumb[output->current_image]); } @@ -1203,6 +1198,9 @@ drm_output_init_pixman(struct drm_output *output, struct drm_backend *b) return -1; } + if (pixman->output_create(&output->base, &options) < 0) + goto err; + /* FIXME error checking */ for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) { output->dumb[i] = drm_fb_create_dumb(device, w, h, format); @@ -1216,17 +1214,16 @@ drm_output_init_pixman(struct drm_output *output, struct drm_backend *b) output->dumb[i]->strides[0]); if (!output->renderbuffer[i]) goto err; - } - if (pixman->output_create(&output->base, &options) < 0) - goto err; + pixman_region32_init_rect(&output->renderbuffer[i]->damage, + output->base.x, output->base.y, + output->base.width, + output->base.height); + } weston_log("DRM: output %s %s shadow framebuffer.\n", output->base.name, b->use_pixman_shadow ? "uses" : "does not use"); - pixman_region32_init_rect(&output->previous_damage, - output->base.x, output->base.y, output->base.width, output->base.height); - return 0; err: @@ -1239,6 +1236,7 @@ err: output->dumb[i] = NULL; output->renderbuffer[i] = NULL; } + pixman->output_destroy(&output->base); return -1; } @@ -1258,15 +1256,14 @@ drm_output_fini_pixman(struct drm_output *output) drm_plane_reset_state(output->scanout_plane); } - renderer->pixman->output_destroy(&output->base); - pixman_region32_fini(&output->previous_damage); - for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) { renderer->pixman->renderbuffer_destroy(output->renderbuffer[i]); drm_fb_unref(output->dumb[i]); output->dumb[i] = NULL; output->renderbuffer[i] = NULL; } + + renderer->pixman->output_destroy(&output->base); } static void diff --git a/libweston/backend-headless/headless.c b/libweston/backend-headless/headless.c index 23a62a31..f0aef7d3 100644 --- a/libweston/backend-headless/headless.c +++ b/libweston/backend-headless/headless.c @@ -192,8 +192,8 @@ headless_output_disable_pixman(struct headless_output *output) { struct weston_renderer *renderer = output->base.compositor->renderer; - renderer->pixman->output_destroy(&output->base); renderer->pixman->renderbuffer_destroy(output->renderbuffer); + renderer->pixman->output_destroy(&output->base); } static int @@ -306,15 +306,15 @@ headless_output_enable_pixman(struct headless_output *output) pixman = output->base.compositor->renderer->pixman; pfmt = pixel_format_get_info(headless_formats[0]); + if (pixman->output_create(&output->base, &options) < 0) + return -1; + output->renderbuffer = pixman->create_image_no_clear(&output->base, pfmt->pixman_format, output->base.current_mode->width, output->base.current_mode->height); if (!output->renderbuffer) - return -1; - - if (pixman->output_create(&output->base, &options) < 0) goto err_renderer; weston_output_update_capture_info(&output->base, @@ -326,7 +326,7 @@ headless_output_enable_pixman(struct headless_output *output) return 0; err_renderer: - pixman->renderbuffer_destroy(output->renderbuffer); + pixman->output_destroy(&output->base); return -1; } diff --git a/libweston/backend-rdp/rdp.c b/libweston/backend-rdp/rdp.c index 8193a706..5cf9812f 100644 --- a/libweston/backend-rdp/rdp.c +++ b/libweston/backend-rdp/rdp.c @@ -481,6 +481,10 @@ rdp_output_enable(struct weston_output *base) b = output->backend; + if (renderer->pixman->output_create(&output->base, &options) < 0) { + return -1; + } + output->renderbuffer = pixman->create_image_from_ptr(&output->base, PIXMAN_x8r8g8b8, output->base.current_mode->width, @@ -489,11 +493,7 @@ rdp_output_enable(struct weston_output *base) output->base.current_mode->width * 4); if (output->renderbuffer == NULL) { weston_log("Failed to create surface for frame buffer.\n"); - return -1; - } - - if (renderer->pixman->output_create(&output->base, &options) < 0) { - renderer->pixman->renderbuffer_destroy(output->renderbuffer); + renderer->pixman->output_destroy(&output->base); return -1; } diff --git a/libweston/libweston-internal.h b/libweston/libweston-internal.h index 00a4e130..debc200d 100644 --- a/libweston/libweston-internal.h +++ b/libweston/libweston-internal.h @@ -48,6 +48,8 @@ struct weston_renderbuffer { pixman_image_t *image; + pixman_region32_t damage; + struct wl_list link; }; struct weston_renderer_options { diff --git a/libweston/pixman-renderer.c b/libweston/pixman-renderer.c index 9bad4652..faef43c5 100644 --- a/libweston/pixman-renderer.c +++ b/libweston/pixman-renderer.c @@ -48,8 +48,8 @@ struct pixman_output_state { const struct pixel_format_info *shadow_format; pixman_image_t *hw_buffer; const struct pixel_format_info *hw_format; - pixman_region32_t *hw_extra_damage; struct weston_size fb_size; + struct wl_list renderbuffer_list; }; struct pixman_surface_state { @@ -627,7 +627,7 @@ pixman_renderer_repaint_output(struct weston_output *output, struct weston_renderbuffer *renderbuffer) { struct pixman_output_state *po = get_output_state(output); - pixman_region32_t hw_damage; + struct weston_renderbuffer *rb; assert(renderbuffer); @@ -636,33 +636,26 @@ pixman_renderer_repaint_output(struct weston_output *output, assert(output->from_blend_to_output_by_backend || output->color_outcome->from_blend_to_output == NULL); - if (!po->hw_buffer) { - po->hw_extra_damage = NULL; + if (!po->hw_buffer) 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); - } + /* Accumulate damage in all renderbuffers */ + wl_list_for_each(rb, &po->renderbuffer_list, link) + pixman_region32_union(&rb->damage, &rb->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, &hw_damage); + copy_to_hw_buffer(output, &renderbuffer->damage); } else { - repaint_surfaces(output, &hw_damage); + repaint_surfaces(output, &renderbuffer->damage); } pixman_renderer_do_capture_tasks(output, WESTON_OUTPUT_CAPTURE_SOURCE_FRAMEBUFFER, po->hw_buffer, po->hw_format); - pixman_region32_fini(&hw_damage); + pixman_region32_clear(&renderbuffer->damage); wl_signal_emit(&output->frame_signal, output_damage); @@ -1063,15 +1056,6 @@ pixman_renderer_output_set_buffer(struct weston_output *output, po->hw_format); } -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; -} - static int pixman_renderer_output_create(struct weston_output *output, const struct pixman_renderer_output_options *options) @@ -1099,6 +1083,8 @@ pixman_renderer_output_create(struct weston_output *output, return -1; } + wl_list_init(&po->renderbuffer_list); + return 0; } @@ -1116,6 +1102,8 @@ pixman_renderer_output_destroy(struct weston_output *output) po->shadow_image = NULL; po->hw_buffer = NULL; + assert(wl_list_empty(&po->renderbuffer_list)); + free(po); } @@ -1124,8 +1112,11 @@ pixman_renderer_create_image_from_ptr(struct weston_output *output, pixman_format_code_t format, int width, int height, uint32_t *ptr, int rowstride) { + struct pixman_output_state *po = get_output_state(output); struct weston_renderbuffer *renderbuffer; + assert(po); + renderbuffer = xzalloc(sizeof(*renderbuffer)); renderbuffer->image = pixman_image_create_bits(format, width, height, @@ -1135,6 +1126,9 @@ pixman_renderer_create_image_from_ptr(struct weston_output *output, return NULL; } + pixman_region32_init(&renderbuffer->damage); + wl_list_insert(&po->renderbuffer_list, &renderbuffer->link); + return renderbuffer; } @@ -1143,8 +1137,11 @@ pixman_renderer_create_image_no_clear(struct weston_output *output, pixman_format_code_t format, int width, int height) { + struct pixman_output_state *po = get_output_state(output); struct weston_renderbuffer *renderbuffer; + assert(po); + renderbuffer = xzalloc(sizeof(*renderbuffer)); renderbuffer->image = @@ -1155,13 +1152,18 @@ pixman_renderer_create_image_no_clear(struct weston_output *output, return NULL; } + pixman_region32_init(&renderbuffer->damage); + wl_list_insert(&po->renderbuffer_list, &renderbuffer->link); + return renderbuffer; } static void pixman_renderer_renderbuffer_destroy(struct weston_renderbuffer *renderbuffer) { + wl_list_remove(&renderbuffer->link); pixman_image_unref(renderbuffer->image); + pixman_region32_fini(&renderbuffer->damage); free(renderbuffer); } diff --git a/libweston/pixman-renderer.h b/libweston/pixman-renderer.h index a54ce6aa..eedd9447 100644 --- a/libweston/pixman-renderer.h +++ b/libweston/pixman-renderer.h @@ -40,10 +40,6 @@ struct pixman_renderer_output_options { struct weston_size fb_size; }; -void -pixman_renderer_output_set_hw_extra_damage(struct weston_output *output, - pixman_region32_t *extra_damage); - struct pixman_renderer_interface { int (*output_create)(struct weston_output *output, const struct pixman_renderer_output_options *options);