[PATCH weston 2/2] window: Don't free shm buffers while the compositor is using them

Ander Conselvan de Oliveira ander.conselvan.de.oliveira at intel.com
Tue Jun 19 03:45:56 PDT 2012


After commit 460a79bd, the compositor will only upload the contents of
an shm buffer to a texture during repaint, but at the point the buffer
might have been destroyed already. In that case, the surface simply
isn't drawn.

The compositor sends a release event when it's done using a buffer, so
this patch delays the destruction until then if necessary.
---
 clients/window.c |   35 ++++++++++++++++++++++++++++++++++-
 1 files changed, 34 insertions(+), 1 deletions(-)

diff --git a/clients/window.c b/clients/window.c
index aaf2009..3ebbbeb 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -327,6 +327,7 @@ static const struct weston_option xkb_options[] = {
 static const cairo_user_data_key_t surface_data_key;
 struct surface_data {
 	struct wl_buffer *buffer;
+	int attach_count;
 };
 
 #define MULT(_d,c,a,t) \
@@ -402,6 +403,7 @@ display_get_buffer_for_surface(struct display *display,
 	struct surface_data *data;
 
 	data = cairo_surface_get_user_data (surface, &surface_data_key);
+	data->attach_count++;
 
 	return data->buffer;
 }
@@ -409,6 +411,7 @@ display_get_buffer_for_surface(struct display *display,
 struct shm_surface_data {
 	struct surface_data data;
 	struct shm_pool *pool;
+	int surface_gone;
 };
 
 static void
@@ -426,6 +429,32 @@ shm_surface_data_destroy(void *p)
 	free(data);
 }
 
+static void
+shm_buffer_destroy(void *p, struct wl_buffer *buffer)
+{
+	struct shm_surface_data *data = p;
+
+	data->data.attach_count = 0;
+
+	if (data->surface_gone)
+		shm_surface_data_destroy(data);
+}
+
+static const struct wl_buffer_listener shm_buffer_listener = {
+	shm_buffer_destroy
+};
+
+static void
+shm_surface_data_unref(void *p)
+{
+	struct shm_surface_data *data = p;
+
+	data->surface_gone = 1;
+
+	if (data->data.attach_count == 0)
+		shm_surface_data_destroy(p);
+}
+
 static struct wl_shm_pool *
 make_shm_pool(struct display *display, int size, void **data)
 {
@@ -543,8 +572,9 @@ display_create_shm_surface_from_pool(struct display *display,
 						       rectangle->height,
 						       stride);
 
+	data->surface_gone = 0;
 	cairo_surface_set_user_data (surface, &surface_data_key,
-				     data, shm_surface_data_destroy);
+				     data, shm_surface_data_unref);
 
 	if (flags & SURFACE_OPAQUE)
 		format = WL_SHM_FORMAT_XRGB8888;
@@ -556,6 +586,9 @@ display_create_shm_surface_from_pool(struct display *display,
 						      rectangle->height,
 						      stride, format);
 
+	data->data.attach_count = 0;
+	wl_buffer_add_listener(data->data.buffer, &shm_buffer_listener, data);
+
 	return surface;
 }
 
-- 
1.7.4.1



More information about the wayland-devel mailing list