From 07734a2564c14e3a0b3a5c7a9897679dc09cc31f Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 26 Jan 2023 16:38:34 +0100 Subject: [PATCH] pixman-renderer: hold a reference for renderbuffers on the output state list Now that struct weston_renderbuffer is refcounted, hold a reference for renderbuffers on the pixman_output_state::renderbuffer_list. This allows backends to destroy the renderer output state and release renderbuffer references in any order without running into an assert(). To avoid breaking resizing, We also have to drop the renderbuffer list during pixman_renderer_resize_output(). The backends have to create new renderbuffers afterwards. Signed-off-by: Philipp Zabel --- libweston/pixman-renderer.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/libweston/pixman-renderer.c b/libweston/pixman-renderer.c index bbb3c383..b4806f2f 100644 --- a/libweston/pixman-renderer.c +++ b/libweston/pixman-renderer.c @@ -920,6 +920,7 @@ pixman_renderer_resize_output(struct weston_output *output, const struct weston_geometry *area) { struct pixman_output_state *po = get_output_state(output); + struct pixman_renderbuffer *renderbuffer, *tmp; check_compositing_area(fb_size, area); @@ -934,6 +935,11 @@ pixman_renderer_resize_output(struct weston_output *output, pixman_renderer_output_set_buffer(output, NULL); + wl_list_for_each_safe(renderbuffer, tmp, &po->renderbuffer_list, link) { + wl_list_remove(&renderbuffer->link); + weston_renderbuffer_unref(&renderbuffer->base); + } + po->fb_size = *fb_size; /* @@ -1100,14 +1106,14 @@ pixman_renderer_output_create(struct weston_output *output, if (options->use_shadow) po->shadow_format = pixel_format_get_info(DRM_FORMAT_XRGB8888); + wl_list_init(&po->renderbuffer_list); + if (!pixman_renderer_resize_output(output, &options->fb_size, &area)) { output->renderer_state = NULL; free(po); return -1; } - wl_list_init(&po->renderbuffer_list); - weston_output_update_capture_info(output, WESTON_OUTPUT_CAPTURE_SOURCE_FRAMEBUFFER, area.width, area.height, @@ -1120,6 +1126,7 @@ static void pixman_renderer_output_destroy(struct weston_output *output) { struct pixman_output_state *po = get_output_state(output); + struct pixman_renderbuffer *renderbuffer, *tmp; if (po->shadow_image) pixman_image_unref(po->shadow_image); @@ -1130,7 +1137,10 @@ pixman_renderer_output_destroy(struct weston_output *output) po->shadow_image = NULL; po->hw_buffer = NULL; - assert(wl_list_empty(&po->renderbuffer_list)); + wl_list_for_each_safe(renderbuffer, tmp, &po->renderbuffer_list, link) { + wl_list_remove(&renderbuffer->link); + weston_renderbuffer_unref(&renderbuffer->base); + } free(po); } @@ -1160,7 +1170,7 @@ pixman_renderer_create_image_from_ptr(struct weston_output *output, } pixman_region32_init(&renderbuffer->base.damage); - renderbuffer->base.refcount = 1; + renderbuffer->base.refcount = 2; renderbuffer->base.destroy = pixman_renderer_renderbuffer_destroy; wl_list_insert(&po->renderbuffer_list, &renderbuffer->link); @@ -1188,7 +1198,7 @@ pixman_renderer_create_image(struct weston_output *output, } pixman_region32_init(&renderbuffer->base.damage); - renderbuffer->base.refcount = 1; + renderbuffer->base.refcount = 2; renderbuffer->base.destroy = pixman_renderer_renderbuffer_destroy; wl_list_insert(&po->renderbuffer_list, &renderbuffer->link); @@ -1201,7 +1211,6 @@ pixman_renderer_renderbuffer_destroy(struct weston_renderbuffer *renderbuffer) struct pixman_renderbuffer *rb; rb = container_of(renderbuffer, struct pixman_renderbuffer, base); - wl_list_remove(&rb->link); pixman_image_unref(rb->image); pixman_region32_fini(&rb->base.damage); free(rb);