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 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel