[mutter/wip/wayland-display: 13/62] squash: Update because wl_shm_buffer is no longer a wl_buffer (1)



commit a7c04e114ed0bb2c0f13ba12faa3caa51cb16448
Author: Neil Roberts <neil linux intel com>
Date:   Mon Jul 8 16:53:54 2013 +0100

    squash: Update because wl_shm_buffer is no longer a wl_buffer (1)
    
    This should be squashed into the commit:
    “wayland: Adds basic hybrid X + Wayland support”
    
    Based on this clayland commit:
    https://github.com/clutter-project/clayland/commit/d08f31d22ad63c

 src/compositor/meta-shaped-texture.c       |   89 +++++++++-------
 src/compositor/meta-window-actor-private.h |    4 +-
 src/compositor/meta-window-actor.c         |    8 +-
 src/meta/meta-shaped-texture.h             |    4 +-
 src/wayland/meta-wayland-private.h         |   27 ++++-
 src/wayland/meta-wayland.c                 |  158 +++++++++++++++++-----------
 6 files changed, 183 insertions(+), 107 deletions(-)
---
diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c
index 23382c8..93d6eeb 100644
--- a/src/compositor/meta-shaped-texture.c
+++ b/src/compositor/meta-shaped-texture.c
@@ -489,8 +489,9 @@ meta_shaped_texture_set_wayland_surface (MetaShapedTexture *stex,
 
   priv->wayland.surface = surface;
 
-  if (surface && surface->buffer)
-    meta_shaped_texture_attach_wayland_buffer (stex, surface->buffer);
+  if (surface && surface->buffer_ref.buffer)
+    meta_shaped_texture_attach_wayland_buffer (stex,
+                                               surface->buffer_ref.buffer);
 }
 
 MetaWaylandSurface *
@@ -566,49 +567,55 @@ wayland_surface_update_area (MetaShapedTexture *stex,
                              int                height)
 {
   MetaShapedTexturePrivate *priv;
-  struct wl_buffer *buffer;
+  MetaWaylandBuffer *buffer;
 
   priv = stex->priv;
 
   g_return_if_fail (priv->type == META_SHAPED_TEXTURE_TYPE_WAYLAND_SURFACE);
   g_return_if_fail (priv->texture != NULL);
 
-  buffer = priv->wayland.surface->buffer;
+  buffer = priv->wayland.surface->buffer_ref.buffer;
 
-  if (buffer && wl_buffer_is_shm (buffer))
+  if (buffer)
     {
-      CoglPixelFormat format;
+      struct wl_resource *resource = buffer->resource;
+      struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (resource);
 
-      switch (wl_shm_buffer_get_format (buffer))
+      if (shm_buffer)
         {
+          CoglPixelFormat format;
+
+          switch (wl_shm_buffer_get_format (shm_buffer))
+            {
 #if G_BYTE_ORDER == G_BIG_ENDIAN
-          case WL_SHM_FORMAT_ARGB8888:
-            format = COGL_PIXEL_FORMAT_ARGB_8888_PRE;
-            break;
-          case WL_SHM_FORMAT_XRGB8888:
-            format = COGL_PIXEL_FORMAT_ARGB_8888;
-            break;
+            case WL_SHM_FORMAT_ARGB8888:
+              format = COGL_PIXEL_FORMAT_ARGB_8888_PRE;
+              break;
+            case WL_SHM_FORMAT_XRGB8888:
+              format = COGL_PIXEL_FORMAT_ARGB_8888;
+              break;
 #elif G_BYTE_ORDER == G_LITTLE_ENDIAN
-          case WL_SHM_FORMAT_ARGB8888:
-            format = COGL_PIXEL_FORMAT_BGRA_8888_PRE;
-            break;
-          case WL_SHM_FORMAT_XRGB8888:
-            format = COGL_PIXEL_FORMAT_BGRA_8888;
-            break;
+            case WL_SHM_FORMAT_ARGB8888:
+              format = COGL_PIXEL_FORMAT_BGRA_8888_PRE;
+              break;
+            case WL_SHM_FORMAT_XRGB8888:
+              format = COGL_PIXEL_FORMAT_BGRA_8888;
+              break;
 #endif
-          default:
-            g_warn_if_reached ();
-            format = COGL_PIXEL_FORMAT_ARGB_8888;
-        }
+            default:
+              g_warn_if_reached ();
+              format = COGL_PIXEL_FORMAT_ARGB_8888;
+            }
 
-      cogl_texture_set_region (priv->texture,
-                               x, y,
-                               x, y,
-                               width, height,
-                               width, height,
-                               format,
-                               wl_shm_buffer_get_stride (buffer),
-                               wl_shm_buffer_get_data (buffer));
+          cogl_texture_set_region (priv->texture,
+                                   x, y,
+                                   x, y,
+                                   width, height,
+                                   width, height,
+                                   format,
+                                   wl_shm_buffer_get_stride (shm_buffer),
+                                   wl_shm_buffer_get_data (shm_buffer));
+        }
     }
 }
 #endif /* HAVE_WAYLAND */
@@ -731,8 +738,8 @@ meta_shaped_texture_set_pixmap (MetaShapedTexture *stex,
 
 #ifdef HAVE_WAYLAND
 void
-meta_shaped_texture_attach_wayland_buffer (MetaShapedTexture *stex,
-                                           struct wl_buffer  *buffer)
+meta_shaped_texture_attach_wayland_buffer (MetaShapedTexture  *stex,
+                                           MetaWaylandBuffer  *buffer)
 {
   MetaShapedTexturePrivate *priv;
 
@@ -745,7 +752,7 @@ meta_shaped_texture_attach_wayland_buffer (MetaShapedTexture *stex,
    * a reference to the MetaWaylandSurface where we can access the
    * buffer without it being explicitly passed as an argument.
    */
-  g_return_if_fail (priv->wayland.surface->buffer == buffer);
+  g_return_if_fail (priv->wayland.surface->buffer_ref.buffer == buffer);
 
   if (buffer)
     {
@@ -753,9 +760,19 @@ meta_shaped_texture_attach_wayland_buffer (MetaShapedTexture *stex,
         clutter_backend_get_cogl_context (clutter_get_default_backend ());
       CoglError *catch_error = NULL;
       CoglTexture *texture =
-        COGL_TEXTURE (cogl_wayland_texture_2d_new_from_buffer (ctx, buffer, &catch_error));
+        COGL_TEXTURE (cogl_wayland_texture_2d_new_from_buffer (ctx,
+                                                               buffer->resource,
+                                                               &catch_error));
       if (!texture)
-        cogl_error_free (catch_error);
+        {
+          cogl_error_free (catch_error);
+        }
+      else
+        {
+          buffer->width = cogl_texture_get_width (texture);
+          buffer->height = cogl_texture_get_height (texture);
+        }
+
       set_cogl_texture (stex, texture);
     }
   else
diff --git a/src/compositor/meta-window-actor-private.h b/src/compositor/meta-window-actor-private.h
index f4f1b47..3f5d8ce 100644
--- a/src/compositor/meta-window-actor-private.h
+++ b/src/compositor/meta-window-actor-private.h
@@ -40,8 +40,8 @@ void meta_window_actor_process_wayland_damage (MetaWindowActor *self,
                                                int              height);
 void meta_window_actor_set_wayland_surface    (MetaWindowActor    *self,
                                                MetaWaylandSurface *surface);
-void meta_window_actor_attach_wayland_buffer  (MetaWindowActor  *self,
-                                               struct wl_buffer *buffer);
+void meta_window_actor_attach_wayland_buffer  (MetaWindowActor   *self,
+                                               MetaWaylandBuffer *buffer);
 #endif
 
 void meta_window_actor_pre_paint      (MetaWindowActor    *self);
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index c838bb2..682b901 100644
--- a/src/compositor/meta-window-actor.c
+++ b/src/compositor/meta-window-actor.c
@@ -2459,7 +2459,7 @@ meta_window_actor_update_shape (MetaWindowActor *self)
 #ifdef HAVE_WAYLAND
 static void
 maybe_emit_size_changed (MetaWindowActor *self,
-                         struct wl_buffer *new_buffer)
+                         MetaWaylandBuffer *new_buffer)
 {
   MetaWindowActorPrivate *priv = self->priv;
   int                     width = 0, height = 0;
@@ -2498,13 +2498,13 @@ meta_window_actor_set_wayland_surface (MetaWindowActor *self,
 
   meta_shaped_texture_set_wayland_surface (META_SHAPED_TEXTURE (priv->actor),
                                            surface);
-  if (surface->buffer)
-    maybe_emit_size_changed (self, surface->buffer);
+  if (surface->buffer_ref.buffer)
+    maybe_emit_size_changed (self, surface->buffer_ref.buffer);
 }
 
 void
 meta_window_actor_attach_wayland_buffer (MetaWindowActor *self,
-                                         struct wl_buffer *buffer)
+                                         MetaWaylandBuffer *buffer)
 {
   MetaWindowActorPrivate *priv = self->priv;
   MetaShapedTexture *stex = META_SHAPED_TEXTURE (priv->actor);
diff --git a/src/meta/meta-shaped-texture.h b/src/meta/meta-shaped-texture.h
index af46bd0..7774ca0 100644
--- a/src/meta/meta-shaped-texture.h
+++ b/src/meta/meta-shaped-texture.h
@@ -94,8 +94,8 @@ void meta_shaped_texture_update_area (MetaShapedTexture *stex,
 void meta_shaped_texture_set_pixmap (MetaShapedTexture *stex,
                                      Pixmap             pixmap);
 #ifdef HAVE_WAYLAND
-void meta_shaped_texture_attach_wayland_buffer (MetaShapedTexture *stex,
-                                                struct wl_buffer  *buffer);
+void meta_shaped_texture_attach_wayland_buffer (MetaShapedTexture  *stex,
+                                                MetaWaylandBuffer  *buffer);
 #endif
 
 CoglTexture * meta_shaped_texture_get_texture (MetaShapedTexture *stex);
diff --git a/src/wayland/meta-wayland-private.h b/src/wayland/meta-wayland-private.h
index 76a1fec..5401746 100644
--- a/src/wayland/meta-wayland-private.h
+++ b/src/wayland/meta-wayland-private.h
@@ -43,6 +43,28 @@ typedef struct _MetaWaylandDataSource MetaWaylandDataSource;
 
 typedef struct
 {
+  struct wl_resource *resource;
+  struct wl_signal destroy_signal;
+  struct wl_listener destroy_listener;
+
+  union
+  {
+    struct wl_shm_buffer *shm_buffer;
+    struct wl_buffer *legacy_buffer;
+  };
+
+  int32_t width, height;
+  uint32_t busy_count;
+} MetaWaylandBuffer;
+
+typedef struct
+{
+  MetaWaylandBuffer *buffer;
+  struct wl_listener destroy_listener;
+} MetaWaylandBufferReference;
+
+typedef struct
+{
   struct wl_resource resource;
   cairo_region_t *region;
 } MetaWaylandRegion;
@@ -54,8 +76,7 @@ struct _MetaWaylandSurface
   guint32 xid;
   int x;
   int y;
-  struct wl_buffer *buffer;
-  struct wl_listener buffer_destroy_listener;
+  MetaWaylandBufferReference buffer_ref;
   MetaWindow *window;
   gboolean has_shell_surface;
 
@@ -64,7 +85,7 @@ struct _MetaWaylandSurface
   {
     /* wl_surface.attach */
     gboolean newly_attached;
-    struct wl_buffer *buffer;
+    MetaWaylandBuffer *buffer;
     struct wl_listener buffer_destroy_listener;
     int32_t sx;
     int32_t sy;
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index eb31b8c..ddd8833 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -128,10 +128,88 @@ wayland_event_source_new (struct wl_display *display)
 }
 
 static void
+meta_wayland_buffer_destroy_handler (struct wl_listener *listener,
+                                     void *data)
+{
+  MetaWaylandBuffer *buffer =
+    wl_container_of (listener, buffer, destroy_listener);
+
+  wl_signal_emit (&buffer->destroy_signal, buffer);
+  g_slice_free (MetaWaylandBuffer, buffer);
+}
+
+static MetaWaylandBuffer *
+meta_wayland_buffer_from_resource (struct wl_resource *resource)
+{
+  MetaWaylandBuffer *buffer;
+  struct wl_listener *listener;
+
+  listener =
+    wl_resource_get_destroy_listener (resource,
+                                      meta_wayland_buffer_destroy_handler);
+
+  if (listener)
+    {
+      buffer = wl_container_of (listener, buffer, destroy_listener);
+    }
+  else
+    {
+      buffer = g_slice_new0 (MetaWaylandBuffer);
+
+      buffer->resource = resource;
+      wl_signal_init (&buffer->destroy_signal);
+      buffer->destroy_listener.notify = meta_wayland_buffer_destroy_handler;
+      wl_resource_add_destroy_listener (resource, &buffer->destroy_listener);
+    }
+
+  return buffer;
+}
+
+static void
+meta_wayland_buffer_reference_handle_destroy (struct wl_listener *listener,
+                                          void *data)
+{
+  MetaWaylandBufferReference *ref =
+    wl_container_of (listener, ref, destroy_listener);
+
+  g_assert (data == ref->buffer);
+
+  ref->buffer = NULL;
+}
+
+static void
+meta_wayland_buffer_reference (MetaWaylandBufferReference *ref,
+                               MetaWaylandBuffer *buffer)
+{
+  if (ref->buffer && buffer != ref->buffer)
+    {
+      ref->buffer->busy_count--;
+
+      if (ref->buffer->busy_count == 0)
+        {
+          g_assert (wl_resource_get_client (ref->buffer->resource));
+          wl_resource_queue_event (ref->buffer->resource, WL_BUFFER_RELEASE);
+        }
+
+      wl_list_remove (&ref->destroy_listener.link);
+    }
+
+  if (buffer && buffer != ref->buffer)
+    {
+      buffer->busy_count++;
+      wl_signal_add (&buffer->destroy_signal, &ref->destroy_listener);
+    }
+
+  ref->buffer = buffer;
+  ref->destroy_listener.notify = meta_wayland_buffer_reference_handle_destroy;
+}
+
+static void
 surface_process_damage (MetaWaylandSurface *surface,
                         cairo_region_t *region)
 {
-  if (surface->window)
+  if (surface->window &&
+      surface->buffer_ref.buffer)
     {
       MetaWindowActor *window_actor =
         META_WINDOW_ACTOR (meta_window_get_compositor_private (surface->window));
@@ -164,51 +242,18 @@ meta_wayland_surface_destroy (struct wl_client *wayland_client,
 }
 
 static void
-meta_wayland_surface_detach_buffer (MetaWaylandSurface *surface)
-{
-  struct wl_buffer *buffer = surface->buffer;
-
-  if (buffer)
-    {
-      wl_list_remove (&surface->buffer_destroy_listener.link);
-
-      surface->buffer = NULL;
-    }
-}
-
-static void
-meta_wayland_surface_detach_buffer_and_notify (MetaWaylandSurface *surface)
-{
-  struct wl_buffer *buffer = surface->buffer;
-
-  if (buffer)
-    {
-      g_assert (buffer->resource.client != NULL);
-      wl_resource_queue_event (&buffer->resource, WL_BUFFER_RELEASE);
-    }
-
-  meta_wayland_surface_detach_buffer (surface);
-}
-
-static void
-surface_handle_buffer_destroy (struct wl_listener *listener,
-                               void *data)
-{
-  MetaWaylandSurface *surface =
-    wl_container_of (listener, surface, buffer_destroy_listener);
-
-  meta_wayland_surface_detach_buffer (surface);
-}
-
-static void
 meta_wayland_surface_attach (struct wl_client *wayland_client,
                              struct wl_resource *wayland_surface_resource,
                              struct wl_resource *wayland_buffer_resource,
                              gint32 sx, gint32 sy)
 {
   MetaWaylandSurface *surface = wayland_surface_resource->data;
-  struct wl_buffer *buffer =
-    wayland_buffer_resource ? wayland_buffer_resource->data : NULL;
+  MetaWaylandBuffer *buffer;
+
+  if (wayland_buffer_resource)
+    buffer = meta_wayland_buffer_from_resource (wayland_buffer_resource);
+  else
+    buffer = NULL;
 
   /* Attach without commit in between does not send wl_buffer.release */
   if (surface->pending.buffer)
@@ -220,7 +265,7 @@ meta_wayland_surface_attach (struct wl_client *wayland_client,
   surface->pending.newly_attached = TRUE;
 
   if (buffer)
-    wl_signal_add (&buffer->resource.destroy_signal,
+    wl_signal_add (&buffer->destroy_signal,
                    &surface->pending.buffer_destroy_listener);
 }
 
@@ -296,18 +341,17 @@ meta_wayland_surface_commit (struct wl_client *client,
 
   /* wl_surface.attach */
   if (surface->pending.newly_attached &&
-      surface->pending.buffer != surface->buffer)
+      surface->buffer_ref.buffer != surface->pending.buffer)
     {
-      struct wl_buffer *buffer = surface->pending.buffer;
-
-      meta_wayland_surface_detach_buffer_and_notify (surface);
+      /* Note: we set this before informing any window-actor since the
+       * window actor will expect to find the new buffer within the
+       * surface. */
+      meta_wayland_buffer_reference (&surface->buffer_ref,
+                                     surface->pending.buffer);
 
       if (surface->pending.buffer)
         {
-          /* Note: we set this before informing any window-actor since
-           * the window actor will expect to find the new buffer
-           * within the surface. */
-          surface->buffer = surface->pending.buffer;
+          MetaWaylandBuffer *buffer = surface->pending.buffer;
 
           if (surface->window)
             {
@@ -319,8 +363,7 @@ meta_wayland_surface_commit (struct wl_client *client,
               meta_window_get_input_rect (surface->window, &rect);
 
               if (window_actor)
-                meta_window_actor_attach_wayland_buffer (window_actor,
-                                                         surface->pending.buffer);
+                meta_window_actor_attach_wayland_buffer (window_actor, buffer);
 
               /* XXX: we resize X based surfaces according to X events */
               if (surface->xid == 0 &&
@@ -329,9 +372,6 @@ meta_wayland_surface_commit (struct wl_client *client,
             }
           else if (surface == compositor->seat->sprite)
             meta_wayland_seat_update_sprite (compositor->seat);
-
-          wl_signal_add (&surface->buffer->resource.destroy_signal,
-                         &surface->buffer_destroy_listener);
         }
     }
 
@@ -405,7 +445,8 @@ meta_wayland_surface_free (MetaWaylandSurface *surface)
   MetaWaylandFrameCallback *cb, *next;
 
   compositor->surfaces = g_list_remove (compositor->surfaces, surface);
-  meta_wayland_surface_detach_buffer_and_notify (surface);
+
+  meta_wayland_buffer_reference (&surface->buffer_ref, NULL);
 
   if (surface->window)
     g_object_weak_unref (G_OBJECT (surface->window),
@@ -476,9 +517,6 @@ meta_wayland_compositor_create_surface (struct wl_client *wayland_client,
 
   surface->pending.damage = cairo_region_create ();
 
-  surface->buffer_destroy_listener.notify =
-    surface_handle_buffer_destroy;
-
   surface->pending.buffer_destroy_listener.notify =
     surface_handle_pending_buffer_destroy;
   wl_list_init (&surface->pending.frame_callback_list);
@@ -884,9 +922,9 @@ ensure_surface_window (MetaWaylandSurface *surface)
     {
       int width, height;
 
-      if (surface->buffer)
+      if (surface->buffer_ref.buffer)
         {
-          struct wl_buffer *buffer = surface->buffer;
+          MetaWaylandBuffer *buffer = surface->buffer_ref.buffer;
           width = buffer->width;
           height = buffer->width;
         }


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