From: Lubomir Rintel Date: Thu, 12 Dec 2013 11:57:56 +0000 (+0100) Subject: pixman: Destroy pixman images when underlying buffer is destroyed X-Git-Tag: 1.3.92~47 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ddc2b1ec326e7b1a178cf5aebf871985fb6b8aca;p=platform%2Fupstream%2Fweston.git pixman: Destroy pixman images when underlying buffer is destroyed While the pixman image might be attached, the underlying buffer might be already gone under certain circumstances. This is easily reproduced by attempting to resize gnome-terminal on a fbdev backend. $ WAYLAND_DEBUG=1 strace -emunmap weston --backend=fbdev-backend.so ... [1524826.942] wl_shm@7.create_pool(new id wl_shm_pool@23, fd 40, 1563540) [1524827.315] wl_shm_pool@23.create_buffer(new id wl_buffer@24, 0, 759, 515, 3036, 0) ... [1524829.488] wl_surface@14.attach(wl_buffer@24, 0, 0) [1524829.766] wl_surface@14.set_buffer_scale(1) [1524829.904] wl_surface@14.damage(0, 0, 759, 515) [1524830.248] wl_surface@14.frame(new id wl_callback@25) [1524830.450] wl_surface@14.commit() ... [1524846.706] wl_shm@7.create_pool(new id wl_shm_pool@26, fd 40, 1545000) [1524847.215] wl_shm_pool@26.create_buffer(new id wl_buffer@27, 0, 750, 515, 3000, 0) [1524847.735] wl_buffer@24.destroy() [1524847.953] -> wl_display@1.delete_id(24) [1524848.144] wl_shm_pool@23.destroy() munmap(0xb5b2e000, 1563540) = 0 [1524849.021] -> wl_display@1.delete_id(23) [1524849.425] wl_surface@14.attach(wl_buffer@27, 0, 0) [1524849.730] wl_surface@14.set_buffer_scale(1) [1524849.821] wl_surface@14.damage(0, 0, 750, 515) Signed-off-by: Lubomir Rintel --- diff --git a/src/pixman-renderer.c b/src/pixman-renderer.c index 7a69578..129affc 100644 --- a/src/pixman-renderer.c +++ b/src/pixman-renderer.c @@ -42,6 +42,7 @@ struct pixman_surface_state { pixman_image_t *image; struct weston_buffer_reference buffer_ref; + struct wl_listener buffer_destroy_listener; struct wl_listener surface_destroy_listener; struct wl_listener renderer_destroy_listener; }; @@ -468,6 +469,22 @@ pixman_renderer_flush_damage(struct weston_surface *surface) } static void +buffer_state_handle_buffer_destroy(struct wl_listener *listener, void *data) +{ + struct pixman_surface_state *ps; + + ps = container_of(listener, struct pixman_surface_state, + buffer_destroy_listener); + + if (ps->image) { + pixman_image_unref(ps->image); + ps->image = NULL; + } + + ps->buffer_destroy_listener.notify = NULL; +} + +static void pixman_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer) { struct pixman_surface_state *ps = get_surface_state(es); @@ -476,6 +493,11 @@ pixman_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer) weston_buffer_reference(&ps->buffer_ref, buffer); + if (ps->buffer_destroy_listener.notify) { + wl_list_remove(&ps->buffer_destroy_listener.link); + ps->buffer_destroy_listener.notify = NULL; + } + if (ps->image) { pixman_image_unref(ps->image); ps->image = NULL; @@ -517,6 +539,11 @@ pixman_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer) buffer->width, buffer->height, wl_shm_buffer_get_data(shm_buffer), wl_shm_buffer_get_stride(shm_buffer)); + + ps->buffer_destroy_listener.notify = + buffer_state_handle_buffer_destroy; + wl_signal_add(&buffer->destroy_signal, + &ps->buffer_destroy_listener); } static void @@ -524,7 +551,10 @@ pixman_renderer_surface_state_destroy(struct pixman_surface_state *ps) { wl_list_remove(&ps->surface_destroy_listener.link); wl_list_remove(&ps->renderer_destroy_listener.link); - + if (ps->buffer_destroy_listener.notify) { + wl_list_remove(&ps->buffer_destroy_listener.link); + ps->buffer_destroy_listener.notify = NULL; + } ps->surface->renderer_state = NULL;