wayland: Add API to acquire a CoglScanout from a surface

This will check whether the current backing buffer is compatible with
the primary plane of the passed CoglOnscreen. Since this will extend the
time before a buffer is released, the MetaWaylandBufferRef is swapped
and orphaned if a new buffer is committed before the previous one was
released. It'll eventually be released, usually by the next page flip
callback.

Currently implemented for EGLImage and DMA-BUF buffer types.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/798
This commit is contained in:
Jonas Ådahl
2019-09-12 11:44:59 +02:00
parent 4b1805c306
commit ff7a42b8bc
6 changed files with 265 additions and 0 deletions

View File

@@ -131,6 +131,13 @@ meta_wayland_buffer_ref_new (void)
return buffer_ref;
}
static MetaWaylandBufferRef *
meta_wayland_buffer_ref_ref (MetaWaylandBufferRef *buffer_ref)
{
g_ref_count_inc (&buffer_ref->ref_count);
return buffer_ref;
}
static void
meta_wayland_buffer_ref_unref (MetaWaylandBufferRef *buffer_ref)
{
@@ -667,6 +674,12 @@ meta_wayland_surface_apply_state (MetaWaylandSurface *surface,
if (surface->buffer_held)
meta_wayland_surface_unref_buffer_use_count (surface);
if (surface->buffer_ref->use_count > 0)
{
meta_wayland_buffer_ref_unref (surface->buffer_ref);
surface->buffer_ref = meta_wayland_buffer_ref_new ();
}
g_set_object (&surface->buffer_ref->buffer, state->buffer);
if (state->buffer)
@@ -1959,3 +1972,38 @@ meta_wayland_surface_get_height (MetaWaylandSurface *surface)
return height / surface->scale;
}
}
static void
scanout_destroyed (gpointer data,
GObject *where_the_object_was)
{
MetaWaylandBufferRef *buffer_ref = data;
meta_wayland_buffer_ref_dec_use_count (buffer_ref);
meta_wayland_buffer_ref_unref (buffer_ref);
}
CoglScanout *
meta_wayland_surface_try_acquire_scanout (MetaWaylandSurface *surface,
CoglOnscreen *onscreen)
{
CoglScanout *scanout;
MetaWaylandBufferRef *buffer_ref;
if (!surface->buffer_ref->buffer)
return NULL;
if (surface->buffer_ref->use_count == 0)
return NULL;
scanout = meta_wayland_buffer_try_acquire_scanout (surface->buffer_ref->buffer,
onscreen);
if (!scanout)
return NULL;
buffer_ref = meta_wayland_buffer_ref_ref (surface->buffer_ref);
meta_wayland_buffer_ref_inc_use_count (buffer_ref);
g_object_weak_ref (G_OBJECT (scanout), scanout_destroyed, buffer_ref);
return scanout;
}