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);