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
This commit is contained in:
Ray Strode 2016-01-31 15:57:29 -05:00
parent 3cdcd3e9c1
commit 0165cb6974
3 changed files with 36 additions and 1 deletions

View File

@ -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)

View File

@ -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);

View File

@ -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;