[PATCH 4/7] pixman-renderer, gl-renderer: Destroy surface state with the renderer

Ander Conselvan de Oliveira ander.conselvan.de.oliveira at intel.com
Fri Oct 25 15:26:34 CEST 2013


Previously the renderers destroy function assumed they are only called
when the compositor is shutting down and that the compositor had
already destroyed all the surfaces. However, if a runtime renderer
switch would be done, the surface state would be leaked.

This patch adds a destroy_signal to the pixman and gl renderers. The
surface state objects will listen for that signal and destroy
themselves if needed.

This is a step towards runtime switchable renderers.
---
 src/gl-renderer.c     |   54 +++++++++++++++++++++++++++++++++++++++++--------
 src/pixman-renderer.c |   41 +++++++++++++++++++++++++++++++++----
 2 files changed, 83 insertions(+), 12 deletions(-)

diff --git a/src/gl-renderer.c b/src/gl-renderer.c
index d792530..c3c6ae9 100644
--- a/src/gl-renderer.c
+++ b/src/gl-renderer.c
@@ -83,6 +83,7 @@ struct gl_surface_state {
 	struct weston_surface *surface;
 
 	struct wl_listener surface_destroy_listener;
+	struct wl_listener renderer_destroy_listener;
 };
 
 struct gl_renderer {
@@ -130,6 +131,8 @@ struct gl_renderer {
 	struct gl_shader invert_color_shader;
 	struct gl_shader solid_shader;
 	struct gl_shader *current_shader;
+
+	struct wl_signal destroy_signal;
 };
 
 static inline struct gl_output_state *
@@ -1149,17 +1152,12 @@ gl_renderer_surface_set_color(struct weston_surface *surface,
 }
 
 static void
-surface_state_handle_surface_destroy(struct wl_listener *listener, void *data)
+surface_state_destroy(struct gl_surface_state *gs, struct gl_renderer *gr)
 {
-	struct gl_surface_state *gs;
-	struct gl_renderer *gr;
-	struct weston_surface *surface = data;
 	int i;
 
-	gr = get_renderer(surface->compositor);
-
-	gs = container_of(listener, struct gl_surface_state,
-			  surface_destroy_listener);
+	wl_list_remove(&gs->surface_destroy_listener.link);
+	wl_list_remove(&gs->renderer_destroy_listener.link);
 
 	gs->surface->renderer_state = NULL;
 
@@ -1173,10 +1171,39 @@ surface_state_handle_surface_destroy(struct wl_listener *listener, void *data)
 	free(gs);
 }
 
+static void
+surface_state_handle_surface_destroy(struct wl_listener *listener, void *data)
+{
+	struct gl_surface_state *gs;
+	struct gl_renderer *gr;
+
+	gs = container_of(listener, struct gl_surface_state,
+			  surface_destroy_listener);
+
+	gr = get_renderer(gs->surface->compositor);
+
+	surface_state_destroy(gs, gr);
+}
+
+static void
+surface_state_handle_renderer_destroy(struct wl_listener *listener, void *data)
+{
+	struct gl_surface_state *gs;
+	struct gl_renderer *gr;
+
+	gr = data;
+
+	gs = container_of(listener, struct gl_surface_state,
+			  renderer_destroy_listener);
+
+	surface_state_destroy(gs, gr);
+}
+
 static int
 gl_renderer_create_surface(struct weston_surface *surface)
 {
 	struct gl_surface_state *gs;
+	struct gl_renderer *gr = get_renderer(surface->compositor);
 
 	gs = calloc(1, sizeof *gs);
 	if (!gs)
@@ -1189,6 +1216,8 @@ gl_renderer_create_surface(struct weston_surface *surface)
 	gs->pitch = 1;
 	gs->y_inverted = 1;
 
+	gs->surface = surface;
+
 	pixman_region32_init(&gs->texture_damage);
 	surface->renderer_state = gs;
 
@@ -1197,6 +1226,11 @@ gl_renderer_create_surface(struct weston_surface *surface)
 	wl_signal_add(&surface->destroy_signal,
 		      &gs->surface_destroy_listener);
 
+	gs->renderer_destroy_listener.notify =
+		surface_state_handle_renderer_destroy;
+	wl_signal_add(&gr->destroy_signal,
+		      &gs->renderer_destroy_listener);
+
 	return 0;
 }
 
@@ -1579,6 +1613,8 @@ gl_renderer_destroy(struct weston_compositor *ec)
 {
 	struct gl_renderer *gr = get_renderer(ec);
 
+	wl_signal_emit(&gr->destroy_signal, gr);
+
 	if (gr->has_bind_display)
 		gr->unbind_display(gr->egl_display, ec->wl_display);
 
@@ -1705,6 +1741,8 @@ gl_renderer_create(struct weston_compositor *ec, EGLNativeDisplayType display,
 
 	wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_RGB565);
 
+	wl_signal_init(&gr->destroy_signal);
+
 	return 0;
 
 err_egl:
diff --git a/src/pixman-renderer.c b/src/pixman-renderer.c
index 98a910c..79c1d5b 100644
--- a/src/pixman-renderer.c
+++ b/src/pixman-renderer.c
@@ -43,6 +43,7 @@ struct pixman_surface_state {
 	struct weston_buffer_reference buffer_ref;
 
 	struct wl_listener surface_destroy_listener;
+	struct wl_listener renderer_destroy_listener;
 };
 
 struct pixman_renderer {
@@ -51,6 +52,8 @@ struct pixman_renderer {
 	int repaint_debug;
 	pixman_image_t *debug_color;
 	struct weston_binding *debug_binding;
+
+	struct wl_signal destroy_signal;
 };
 
 static inline struct pixman_output_state *
@@ -593,12 +596,11 @@ pixman_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
 }
 
 static void
-surface_state_handle_surface_destroy(struct wl_listener *listener, void *data)
+pixman_renderer_surface_state_destroy(struct pixman_surface_state *ps)
 {
-	struct pixman_surface_state *ps;
+	wl_list_remove(&ps->surface_destroy_listener.link);
+	wl_list_remove(&ps->renderer_destroy_listener.link);
 
-	ps = container_of(listener, struct pixman_surface_state,
-			  surface_destroy_listener);
 
 	ps->surface->renderer_state = NULL;
 
@@ -610,10 +612,33 @@ surface_state_handle_surface_destroy(struct wl_listener *listener, void *data)
 	free(ps);
 }
 
+static void
+surface_state_handle_surface_destroy(struct wl_listener *listener, void *data)
+{
+	struct pixman_surface_state *ps;
+
+	ps = container_of(listener, struct pixman_surface_state,
+			  surface_destroy_listener);
+
+	pixman_renderer_surface_state_destroy(ps);
+}
+
+static void
+surface_state_handle_renderer_destroy(struct wl_listener *listener, void *data)
+{
+	struct pixman_surface_state *ps;
+
+	ps = container_of(listener, struct pixman_surface_state,
+			  renderer_destroy_listener);
+
+	pixman_renderer_surface_state_destroy(ps);
+}
+
 static int
 pixman_renderer_create_surface(struct weston_surface *surface)
 {
 	struct pixman_surface_state *ps;
+	struct pixman_renderer *pr = get_renderer(surface->compositor);
 
 	ps = calloc(1, sizeof *ps);
 	if (!ps)
@@ -628,6 +653,11 @@ pixman_renderer_create_surface(struct weston_surface *surface)
 	wl_signal_add(&surface->destroy_signal,
 		      &ps->surface_destroy_listener);
 
+	ps->renderer_destroy_listener.notify =
+		surface_state_handle_renderer_destroy;
+	wl_signal_add(&pr->destroy_signal,
+		      &ps->renderer_destroy_listener);
+
 	return 0;
 }
 
@@ -656,6 +686,7 @@ pixman_renderer_destroy(struct weston_compositor *ec)
 {
 	struct pixman_renderer *pr = get_renderer(ec);
 
+	wl_signal_emit(&pr->destroy_signal, pr);
 	weston_binding_destroy(pr->debug_binding);
 	free(pr);
 
@@ -710,6 +741,8 @@ pixman_renderer_init(struct weston_compositor *ec)
 
 	wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_RGB565);
 
+	wl_signal_init(&renderer->destroy_signal);
+
 	return 0;
 }
 
-- 
1.7.9.5



More information about the wayland-devel mailing list