wayland: Add support for EGLStream client buffers

This commit adds for a new type of buffer being attached to a Wayland
surface: buffers from an EGLStream. These buffers behave very
differently from regular Wayland buffers; instead of each buffer
reperesenting an actual frame, the same buffer is attached over and
over again, and EGL API is used to switch the content of the OpenGL
texture associated with the buffer attached. It more or less
side-tracks the Wayland buffer handling.

It is implemented by creating a MetaWaylandEglStream object, dealing
with the EGLStream state. The lifetime of the MetaWaylandEglStream is
tied to the texture object (CoglTexture), which is referenced-counted
and owned by both the actors and the MetaWaylandBuffer.

When the buffer is reattached and committed, the EGLStream is triggered
to switch the content of the associated texture to the new content.
This means that one cannot keep old texture content around without
copying, so any feature relying on that will effectively be broken.

https://bugzilla.gnome.org/show_bug.cgi?id=773629
This commit is contained in:
Jonas Ådahl
2016-10-20 15:59:09 +08:00
parent f5bdf75f70
commit eed4dab0fc
7 changed files with 406 additions and 0 deletions

View File

@ -86,6 +86,7 @@ typedef enum _MetaWaylandBufferType
META_WAYLAND_BUFFER_TYPE_UNKNOWN,
META_WAYLAND_BUFFER_TYPE_SHM,
META_WAYLAND_BUFFER_TYPE_EGL_IMAGE,
META_WAYLAND_BUFFER_TYPE_EGL_STREAM,
} MetaWaylandBufferType;
static MetaWaylandBufferType
@ -107,6 +108,9 @@ determine_buffer_type (MetaWaylandBuffer *buffer)
NULL))
return META_WAYLAND_BUFFER_TYPE_EGL_IMAGE;
if (meta_wayland_is_egl_stream_buffer (buffer))
return META_WAYLAND_BUFFER_TYPE_EGL_STREAM;
return META_WAYLAND_BUFFER_TYPE_UNKNOWN;
}
@ -276,6 +280,39 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
return TRUE;
}
static gboolean
egl_stream_buffer_attach (MetaWaylandBuffer *buffer,
GError **error)
{
MetaWaylandEglStream *stream;
stream = buffer->egl_stream.stream;
if (!stream)
stream = meta_wayland_egl_stream_new (buffer, error);
if (!stream)
return FALSE;
buffer->egl_stream.stream = stream;
if (!buffer->texture)
{
CoglTexture2D *texture;
texture = meta_wayland_egl_stream_create_texture (stream, error);
if (!texture)
return FALSE;
buffer->texture = COGL_TEXTURE (texture);
buffer->is_y_inverted = meta_wayland_egl_stream_is_y_inverted (stream);
}
if (!meta_wayland_egl_stream_attach (stream, error))
return FALSE;
return TRUE;
}
gboolean
meta_wayland_buffer_attach (MetaWaylandBuffer *buffer,
GError **error)
@ -292,6 +329,9 @@ meta_wayland_buffer_attach (MetaWaylandBuffer *buffer,
return shm_buffer_attach (buffer, error);
case META_WAYLAND_BUFFER_TYPE_EGL_IMAGE:
return egl_image_buffer_attach (buffer, error);
case META_WAYLAND_BUFFER_TYPE_EGL_STREAM:
return egl_stream_buffer_attach (buffer, error);
break;
case META_WAYLAND_BUFFER_TYPE_UNKNOWN:
g_set_error (error, G_IO_ERROR,
G_IO_ERROR_FAILED,
@ -308,6 +348,15 @@ meta_wayland_buffer_get_texture (MetaWaylandBuffer *buffer)
return buffer->texture;
}
CoglSnippet *
meta_wayland_buffer_create_snippet (MetaWaylandBuffer *buffer)
{
if (!buffer->egl_stream.stream)
return NULL;
return meta_wayland_egl_stream_create_snippet ();
}
gboolean
meta_wayland_buffer_is_y_inverted (MetaWaylandBuffer *buffer)
{
@ -376,6 +425,7 @@ meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer,
case META_WAYLAND_BUFFER_TYPE_SHM:
res = process_shm_buffer_damage (buffer, region, &error);
case META_WAYLAND_BUFFER_TYPE_EGL_IMAGE:
case META_WAYLAND_BUFFER_TYPE_EGL_STREAM:
res = TRUE;
break;
case META_WAYLAND_BUFFER_TYPE_UNKNOWN:
@ -398,6 +448,7 @@ meta_wayland_buffer_finalize (GObject *object)
MetaWaylandBuffer *buffer = META_WAYLAND_BUFFER (object);
g_clear_pointer (&buffer->texture, cogl_object_unref);
g_clear_object (&buffer->egl_stream.stream);
G_OBJECT_CLASS (meta_wayland_buffer_parent_class)->finalize (object);
}