pixman-renderer, gl-renderer: Destroy surface state with the renderer
authorAnder Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Fri, 25 Oct 2013 13:26:34 +0000 (16:26 +0300)
committerKristian Høgsberg <krh@bitplanet.net>
Fri, 25 Oct 2013 19:21:51 +0000 (12:21 -0700)
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
src/pixman-renderer.c

index 0c0f2d9..d181c07 100644 (file)
@@ -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:
index 98a910c..79c1d5b 100644 (file)
@@ -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;
 }