[mutter] wayland: Don't unset surface->buffer when wl_buffer destroyed



commit d340c3a6dde4b1bec0cda47d30a6b9db62bd5e4e
Author: Jonas Ådahl <jadahl gmail com>
Date:   Fri Feb 26 17:47:21 2016 +0800

    wayland: Don't unset surface->buffer when wl_buffer destroyed
    
    Don't unset the surface->buffer if the associated wl_buffer object is
    destroyed. The MetaWaylandBuffer doesn't really only represent a
    wl_buffer object, but also the data (texture) created from the given
    wl_buffer. Thus, for example destroying a released SHM wl_buffer should
    not destroy the MetaWaylandBuffer instance, because the texture may
    still be used.
    
    This commit also fixes a race where calc_showing would hide a window
    because, at the time of calculation whether it should be showing, the
    surface's buffer had been destroyed as described above.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=762716

 src/wayland/meta-wayland-buffer.c  |   54 +++++++++++++++++++++--------------
 src/wayland/meta-wayland-buffer.h  |    9 ++++--
 src/wayland/meta-wayland-surface.c |   24 +--------------
 src/wayland/meta-wayland-surface.h |    1 -
 4 files changed, 40 insertions(+), 48 deletions(-)
---
diff --git a/src/wayland/meta-wayland-buffer.c b/src/wayland/meta-wayland-buffer.c
index 11db632..3fc5362 100644
--- a/src/wayland/meta-wayland-buffer.c
+++ b/src/wayland/meta-wayland-buffer.c
@@ -30,6 +30,8 @@
 #include <cogl/cogl-wayland-server.h>
 #include <meta/util.h>
 
+G_DEFINE_TYPE (MetaWaylandBuffer, meta_wayland_buffer, G_TYPE_OBJECT);
+
 static void
 meta_wayland_buffer_destroy_handler (struct wl_listener *listener,
                                      void *data)
@@ -37,32 +39,16 @@ meta_wayland_buffer_destroy_handler (struct wl_listener *listener,
   MetaWaylandBuffer *buffer =
     wl_container_of (listener, buffer, destroy_listener);
 
+  buffer->resource = NULL;
   wl_signal_emit (&buffer->destroy_signal, buffer);
-  g_slice_free (MetaWaylandBuffer, buffer);
-}
-
-void
-meta_wayland_buffer_ref (MetaWaylandBuffer *buffer)
-{
-  buffer->ref_count++;
-}
-
-void
-meta_wayland_buffer_unref (MetaWaylandBuffer *buffer)
-{
-  buffer->ref_count--;
-
-  if (buffer->ref_count == 0)
-    {
-      g_warn_if_fail (buffer->use_count == 0);
-
-      g_clear_pointer (&buffer->texture, cogl_object_unref);
-    }
+  g_object_unref (buffer);
 }
 
 void
 meta_wayland_buffer_ref_use_count (MetaWaylandBuffer *buffer)
 {
+  g_warn_if_fail (buffer->resource);
+
   buffer->use_count++;
 }
 
@@ -73,7 +59,7 @@ meta_wayland_buffer_unref_use_count (MetaWaylandBuffer *buffer)
 
   buffer->use_count--;
 
-  if (buffer->use_count == 0)
+  if (buffer->use_count == 0 && buffer->resource)
     wl_resource_queue_event (buffer->resource, WL_BUFFER_RELEASE);
 }
 
@@ -93,7 +79,7 @@ meta_wayland_buffer_from_resource (struct wl_resource *resource)
     }
   else
     {
-      buffer = g_slice_new0 (MetaWaylandBuffer);
+      buffer = g_object_new (META_TYPE_WAYLAND_BUFFER, NULL);
 
       buffer->resource = resource;
       wl_signal_init (&buffer->destroy_signal);
@@ -113,6 +99,7 @@ meta_wayland_buffer_ensure_texture (MetaWaylandBuffer *buffer)
   struct wl_shm_buffer *shm_buffer;
 
   g_return_val_if_fail (buffer->use_count != 0, NULL);
+  g_return_val_if_fail (buffer->resource, NULL);
 
   if (buffer->texture)
     goto out;
@@ -172,3 +159,26 @@ meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer,
       wl_shm_buffer_end_access (shm_buffer);
     }
 }
+
+static void
+meta_wayland_buffer_finalize (GObject *object)
+{
+  MetaWaylandBuffer *buffer = META_WAYLAND_BUFFER (object);
+
+  g_clear_pointer (&buffer->texture, cogl_object_unref);
+
+  G_OBJECT_CLASS (meta_wayland_buffer_parent_class)->finalize (object);
+}
+
+static void
+meta_wayland_buffer_init (MetaWaylandBuffer *buffer)
+{
+}
+
+static void
+meta_wayland_buffer_class_init (MetaWaylandBufferClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = meta_wayland_buffer_finalize;
+}
diff --git a/src/wayland/meta-wayland-buffer.h b/src/wayland/meta-wayland-buffer.h
index fda534b..e9b0aa2 100644
--- a/src/wayland/meta-wayland-buffer.h
+++ b/src/wayland/meta-wayland-buffer.h
@@ -33,18 +33,21 @@
 
 struct _MetaWaylandBuffer
 {
+  GObject parent;
+
   struct wl_resource *resource;
   struct wl_signal destroy_signal;
   struct wl_listener destroy_listener;
 
   CoglTexture *texture;
-  uint32_t ref_count;
   uint32_t use_count;
 };
 
+#define META_TYPE_WAYLAND_BUFFER (meta_wayland_buffer_get_type ())
+G_DECLARE_FINAL_TYPE (MetaWaylandBuffer, meta_wayland_buffer,
+                      META, WAYLAND_BUFFER, GObject);
+
 MetaWaylandBuffer *     meta_wayland_buffer_from_resource       (struct wl_resource    *resource);
-void                    meta_wayland_buffer_ref                 (MetaWaylandBuffer     *buffer);
-void                    meta_wayland_buffer_unref               (MetaWaylandBuffer     *buffer);
 void                    meta_wayland_buffer_ref_use_count       (MetaWaylandBuffer     *buffer);
 void                    meta_wayland_buffer_unref_use_count     (MetaWaylandBuffer     *buffer);
 CoglTexture *           meta_wayland_buffer_ensure_texture      (MetaWaylandBuffer     *buffer);
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index cff4373..f3621a9 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -201,28 +201,9 @@ surface_set_buffer (MetaWaylandSurface *surface,
     return;
 
   if (surface->buffer)
-    {
-      wl_list_remove (&surface->buffer_destroy_listener.link);
-
-      surface_stop_using_buffer (surface);
-      meta_wayland_buffer_unref (surface->buffer);
-    }
-
-  surface->buffer = buffer;
-
-  if (surface->buffer)
-    {
-      meta_wayland_buffer_ref (surface->buffer);
-      wl_signal_add (&surface->buffer->destroy_signal, &surface->buffer_destroy_listener);
-    }
-}
-
-static void
-surface_handle_buffer_destroy (struct wl_listener *listener, void *data)
-{
-  MetaWaylandSurface *surface = wl_container_of (listener, surface, buffer_destroy_listener);
+    surface_stop_using_buffer (surface);
 
-  surface_set_buffer (surface, NULL);
+  g_set_object (&surface->buffer, buffer);
 }
 
 static void
@@ -1192,7 +1173,6 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor,
   surface->resource = wl_resource_create (client, &wl_surface_interface, wl_resource_get_version 
(compositor_resource), id);
   wl_resource_set_implementation (surface->resource, &meta_wayland_wl_surface_interface, surface, 
wl_surface_destructor);
 
-  surface->buffer_destroy_listener.notify = surface_handle_buffer_destroy;
   surface->surface_actor = g_object_ref_sink (meta_surface_actor_wayland_new (surface));
 
   wl_list_init (&surface->pending_frame_callback_list);
diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h
index 4a2c244..a153176 100644
--- a/src/wayland/meta-wayland-surface.h
+++ b/src/wayland/meta-wayland-surface.h
@@ -153,7 +153,6 @@ struct _MetaWaylandSurface
   MetaWindow *window;
   MetaWaylandBuffer *buffer;
   gboolean using_buffer;
-  struct wl_listener buffer_destroy_listener;
   cairo_region_t *input_region;
   cairo_region_t *opaque_region;
   int scale;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]