[mutter] wayland: release buffer after processing commit



commit 0165cb697466ba0843b993416e00d4f768c00d45
Author: Ray Strode <rstrode redhat com>
Date:   Sun Jan 31 15:57:29 2016 -0500

    wayland: release buffer after processing commit
    
    When a client is ready for the compositor to read a surface's
    shared memory buffer, it tells the compositor via
    wl_surface_commit.
    
    From that point forward, the baton is given to the compositor:
    it knows it can read the buffer without worring about the client
    making changes out from under it.
    
    After the compositor has uploaded the pixel contents to the video
    card it is supposed to release the buffer back to the client so that
    the client can reuse it for future use.
    
    At the moment, mutter only releases the buffer when a new buffer
    is attached.  This is problematic, since it means the client has
    to have a second buffer prepared before the compositor gives the
    first one back.  Preparing the second buffer potentially involves
    copying megabytes of pixel data, so that's suboptimal, and there's
    no reason mutter couldn't release the buffer earlier.
    
    This commit changes mutter to release a surface's buffer as soon
    as it's done processing the commit request.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=761312

 src/wayland/meta-wayland-buffer.c  |   29 ++++++++++++++++++++++++++++-
 src/wayland/meta-wayland-buffer.h  |    4 ++++
 src/wayland/meta-wayland-surface.c |    4 ++++
 3 files changed, 36 insertions(+), 1 deletions(-)
---
diff --git a/src/wayland/meta-wayland-buffer.c b/src/wayland/meta-wayland-buffer.c
index f2cf1e7..bb0e8d2 100644
--- a/src/wayland/meta-wayland-buffer.c
+++ b/src/wayland/meta-wayland-buffer.c
@@ -54,10 +54,31 @@ meta_wayland_buffer_unref (MetaWaylandBuffer *buffer)
   if (buffer->ref_count == 0)
     {
       g_clear_pointer (&buffer->texture, cogl_object_unref);
-      wl_resource_queue_event (buffer->resource, WL_BUFFER_RELEASE);
+
+      if (buffer->accessible)
+        meta_wayland_buffer_release_control (buffer);
     }
 }
 
+void
+meta_wayland_buffer_take_control (MetaWaylandBuffer *buffer)
+{
+  if (buffer->accessible)
+    meta_fatal ("buffer control taken twice");
+
+  buffer->accessible = TRUE;
+}
+
+void
+meta_wayland_buffer_release_control (MetaWaylandBuffer *buffer)
+{
+  if (!buffer->accessible)
+    meta_fatal ("buffer released when not in control");
+
+  wl_resource_queue_event (buffer->resource, WL_BUFFER_RELEASE);
+  buffer->accessible = FALSE;
+}
+
 MetaWaylandBuffer *
 meta_wayland_buffer_from_resource (struct wl_resource *resource)
 {
@@ -93,6 +114,9 @@ meta_wayland_buffer_ensure_texture (MetaWaylandBuffer *buffer)
   CoglTexture *texture;
   struct wl_shm_buffer *shm_buffer;
 
+  if (!buffer->accessible)
+    meta_warning ("attempted to process damage on uncommitted buffer");
+
   if (buffer->texture)
     goto out;
 
@@ -126,6 +150,9 @@ meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer,
 {
   struct wl_shm_buffer *shm_buffer;
 
+  if (!buffer->accessible)
+    meta_warning ("attempted to process damage on uncommitted buffer");
+
   shm_buffer = wl_shm_buffer_get (buffer->resource);
 
   if (shm_buffer)
diff --git a/src/wayland/meta-wayland-buffer.h b/src/wayland/meta-wayland-buffer.h
index 8d81c72..9f6a5bf 100644
--- a/src/wayland/meta-wayland-buffer.h
+++ b/src/wayland/meta-wayland-buffer.h
@@ -39,11 +39,15 @@ struct _MetaWaylandBuffer
 
   CoglTexture *texture;
   uint32_t ref_count;
+
+  uint32_t accessible : 1;
 };
 
 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_take_control        (MetaWaylandBuffer     *buffer);
+void                    meta_wayland_buffer_release_control     (MetaWaylandBuffer     *buffer);
 CoglTexture *           meta_wayland_buffer_ensure_texture      (MetaWaylandBuffer     *buffer);
 void                    meta_wayland_buffer_process_damage      (MetaWaylandBuffer     *buffer,
                                                                  cairo_region_t        *region);
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index f9b3f3c..4f8b244 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -596,6 +596,7 @@ apply_pending_state (MetaWaylandSurface      *surface,
 
       if (pending->buffer)
         {
+          meta_wayland_buffer_take_control (pending->buffer);
           CoglTexture *texture = meta_wayland_buffer_ensure_texture (pending->buffer);
           meta_surface_actor_wayland_set_texture (META_SURFACE_ACTOR_WAYLAND (surface->surface_actor), 
texture);
         }
@@ -607,6 +608,9 @@ apply_pending_state (MetaWaylandSurface      *surface,
   if (!cairo_region_is_empty (pending->damage))
     surface_process_damage (surface, pending->damage);
 
+  if (pending->buffer)
+    meta_wayland_buffer_release_control (pending->buffer);
+
   surface->offset_x += pending->dx;
   surface->offset_y += pending->dy;
 


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