From 8061df15441910037be4ef633744f1bfb52efff5 Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Mon, 3 Feb 2014 18:45:32 -0500 Subject: [PATCH] gdkwindow-wayland: Obey Wayland buffer semantics We can't destroy buffers if they're in-use by the compositor. Well, technically we can, but that is considered undefined by Wayland and mutter won't cope with it very well -- it simply kills the client. To solve this, we need to delay the destroy operation until the compositor tells us that it's released the buffer. To do this, hold an extra ref on the cairo surface as long as the surface is in-use by the compositor. --- gdk/wayland/gdkwindow-wayland.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/gdk/wayland/gdkwindow-wayland.c b/gdk/wayland/gdkwindow-wayland.c index 025b03ba22..41a69988a3 100644 --- a/gdk/wayland/gdkwindow-wayland.c +++ b/gdk/wayland/gdkwindow-wayland.c @@ -417,7 +417,11 @@ on_frame_clock_after_paint (GdkFrameClock *clock, data = cairo_surface_get_user_data (impl->cairo_surface, &gdk_wayland_cairo_key); - data->busy = TRUE; + if (!data->busy) + { + data->busy = TRUE; + cairo_surface_reference (impl->cairo_surface); + } } static void @@ -610,7 +614,6 @@ gdk_wayland_cairo_surface_destroy (void *p) g_free (data); } - struct wl_shm_pool * _create_shm_pool (struct wl_shm *shm, int width, @@ -667,9 +670,11 @@ static void buffer_release_callback (void *_data, struct wl_buffer *wl_buffer) { - GdkWaylandCairoSurfaceData *data = _data; + cairo_surface_t *surface = _data; + GdkWaylandCairoSurfaceData *data = cairo_surface_get_user_data (surface, &gdk_wayland_cairo_key); data->busy = FALSE; + cairo_surface_destroy (surface); } static const struct wl_buffer_listener buffer_listener = { @@ -702,17 +707,17 @@ gdk_wayland_create_cairo_surface (GdkWaylandDisplay *display, &data->buf_length, &data->buf); - data->buffer = wl_shm_pool_create_buffer (data->pool, 0, - width*scale, height*scale, - stride*scale, WL_SHM_FORMAT_ARGB8888); - wl_buffer_add_listener (data->buffer, &buffer_listener, data); - surface = cairo_image_surface_create_for_data (data->buf, CAIRO_FORMAT_ARGB32, width*scale, height*scale, stride*scale); + data->buffer = wl_shm_pool_create_buffer (data->pool, 0, + width*scale, height*scale, + stride*scale, WL_SHM_FORMAT_ARGB8888); + wl_buffer_add_listener (data->buffer, &buffer_listener, surface); + cairo_surface_set_user_data (surface, &gdk_wayland_cairo_key, data, gdk_wayland_cairo_surface_destroy);