[PATCH weston 2/2] window: Don't free shm buffers while the compositor is using them
Ander Conselvan de Oliveira
conselvan2 at gmail.com
Wed Jun 20 00:16:22 PDT 2012
On 06/20/2012 08:00 AM, Kristian Høgsberg wrote:
> On Tue, Jun 19, 2012 at 12:04:12PM -0400, Kristian Høgsberg wrote:
>> On Tue, Jun 19, 2012 at 01:45:56PM +0300, Ander Conselvan de Oliveira wrote:
>>> 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.
>>
>> Yeah, I think we need to change the semantics of destroying a buffer
>> that's attached to a surface. Currently (or used to be before my
>> commit broke it) you can attach a buffer and then destroy it
>> immediately, but the surface keeps the contents and remains visible.
>> The idea is that attaching has copy-semantics, or at least that the
>> surface references the underlying content of the buffer (gem buffer or
>> shm buffer for example), but not the buffer itself. That's probably a
>> little too subtle and under-defined. It also leads to some
>> awkwardness inside weston, where we can't just look at surface->buffer
>> to see if a buffer is attached (surface->buffer may be NULL, but we
>> may have a valid EGLImage, for example).
>>
>> So let's just fix that and say that destroying a buffer that's
>> attached to a surface is equivalent to attaching NULL, ie hiding the
>> surface.
>
> Ok, having thought about this some more, I don't we'll change it after
> all. The semantics we have now is not that unusual, the problem is
> that we're batching more and more work in the repaint and in this case
> it broke the shm texture updating. I think we just need to flush the
> batched up damage when the buffer is detroyed instead. Does this work
> for you?
Makes sense. The patch does fix the problem on my end.
Thanks,
Ander
> Kristian
>
> diff --git a/src/compositor.c b/src/compositor.c
> index 00b8f3e..e98a1a7 100644
> --- a/src/compositor.c
> +++ b/src/compositor.c
> @@ -180,12 +180,18 @@ weston_client_launch(struct weston_compositor *compositor,
> }
>
> static void
> +update_shm_texture(struct weston_surface *surface);
> +
> +static void
> surface_handle_buffer_destroy(struct wl_listener *listener, void *data)
> {
> struct weston_surface *es =
> container_of(listener, struct weston_surface,
> buffer_destroy_listener);
>
> + if (es->buffer&& wl_buffer_is_shm(es->buffer))
> + update_shm_texture(es);
> +
> es->buffer = NULL;
> }
>
>
>
>>> 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
>>>
>>> _______________________________________________
>>> wayland-devel mailing list
>>> wayland-devel at lists.freedesktop.org
>>> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
More information about the wayland-devel
mailing list