wayland/dma-buf: Add meta_wayland_dma_buf_create_source
Creates a GSource which will call the specified dispatch callback when all dma-buf file descriptors for the buffer have become readable. v2: * Hold a reference to the buffer in the source, to prevent the buffer from getting destroyed before the source. v3: * Do not use check callback, handle everything in dispatch callback. (Dor Askayo) v4: (Georges Basile Stavracas Neto) * Define and use MetaWaylandDmaBufSource & MetaWaylandDmaBufSourceDispatch types. * Fix meta_wayland_dma_buf_source_dispatch & meta_wayland_dma_buf_source_funcs formatting. * Use gpointer instead of void*. * Rename meta_wayland_dma_buf_get_source to meta_wayland_dma_buf_create_source. (Carlos Garnacho) v5: * Explicitly handle NULL return value. (Jonas Ådahl) v6: * Fix style issue per check-style.py. v7: * Fix code style harder. (Jonas Ådahl) Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
This commit is contained in:
parent
416285d1b7
commit
d43150573e
@ -763,6 +763,153 @@ meta_wayland_dma_buf_from_buffer (MetaWaylandBuffer *buffer)
|
||||
return buffer->dma_buf.dma_buf;
|
||||
}
|
||||
|
||||
typedef struct _MetaWaylandDmaBufSource
|
||||
{
|
||||
GSource base;
|
||||
|
||||
MetaWaylandDmaBufSourceDispatch dispatch;
|
||||
MetaWaylandBuffer *buffer;
|
||||
gpointer user_data;
|
||||
|
||||
gpointer fd_tags[META_WAYLAND_DMA_BUF_MAX_FDS];
|
||||
} MetaWaylandDmaBufSource;
|
||||
|
||||
static gboolean
|
||||
meta_wayland_dma_buf_fd_readable (int fd)
|
||||
{
|
||||
GPollFD poll_fd;
|
||||
|
||||
poll_fd.fd = fd;
|
||||
poll_fd.events = G_IO_IN;
|
||||
poll_fd.revents = 0;
|
||||
|
||||
if (!g_poll (&poll_fd, 1, 0))
|
||||
return FALSE;
|
||||
|
||||
return (poll_fd.revents & (G_IO_IN | G_IO_NVAL)) != 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_wayland_dma_buf_source_dispatch (GSource *base,
|
||||
GSourceFunc callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaWaylandDmaBufSource *source;
|
||||
MetaWaylandDmaBufBuffer *dma_buf;
|
||||
gboolean ready;
|
||||
uint32_t i;
|
||||
|
||||
source = (MetaWaylandDmaBufSource *) base;
|
||||
dma_buf = source->buffer->dma_buf.dma_buf;
|
||||
ready = TRUE;
|
||||
|
||||
for (i = 0; i < META_WAYLAND_DMA_BUF_MAX_FDS; i++)
|
||||
{
|
||||
gpointer fd_tag = source->fd_tags[i];
|
||||
|
||||
if (!fd_tag)
|
||||
continue;
|
||||
|
||||
if (!meta_wayland_dma_buf_fd_readable (dma_buf->fds[i]))
|
||||
{
|
||||
ready = FALSE;
|
||||
continue;
|
||||
}
|
||||
|
||||
g_source_remove_unix_fd (&source->base, fd_tag);
|
||||
source->fd_tags[i] = NULL;
|
||||
}
|
||||
|
||||
if (!ready)
|
||||
return G_SOURCE_CONTINUE;
|
||||
|
||||
source->dispatch (source->buffer, source->user_data);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_dma_buf_source_finalize (GSource *base)
|
||||
{
|
||||
MetaWaylandDmaBufSource *source;
|
||||
uint32_t i;
|
||||
|
||||
source = (MetaWaylandDmaBufSource *) base;
|
||||
|
||||
for (i = 0; i < META_WAYLAND_DMA_BUF_MAX_FDS; i++)
|
||||
{
|
||||
gpointer fd_tag = source->fd_tags[i];
|
||||
|
||||
if (fd_tag)
|
||||
{
|
||||
g_source_remove_unix_fd (&source->base, fd_tag);
|
||||
source->fd_tags[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
g_clear_object (&source->buffer);
|
||||
}
|
||||
|
||||
static GSourceFuncs meta_wayland_dma_buf_source_funcs = {
|
||||
.dispatch = meta_wayland_dma_buf_source_dispatch,
|
||||
.finalize = meta_wayland_dma_buf_source_finalize
|
||||
};
|
||||
|
||||
/**
|
||||
* meta_wayland_dma_buf_create_source:
|
||||
* @buffer: A #MetaWaylandBuffer object
|
||||
* @dispatch: Callback
|
||||
* @user_data: User data for the callback
|
||||
*
|
||||
* Creates a GSource which will call the specified dispatch callback when all
|
||||
* dma-buf file descriptors for the buffer have become readable.
|
||||
*
|
||||
* Returns: The new GSource (or
|
||||
* %NULL if there are no dma-buf file descriptors, or they were all readable
|
||||
* already)
|
||||
*/
|
||||
GSource *
|
||||
meta_wayland_dma_buf_create_source (MetaWaylandBuffer *buffer,
|
||||
MetaWaylandDmaBufSourceDispatch dispatch,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaWaylandDmaBufBuffer *dma_buf;
|
||||
MetaWaylandDmaBufSource *source = NULL;
|
||||
uint32_t i;
|
||||
|
||||
dma_buf = buffer->dma_buf.dma_buf;
|
||||
if (!dma_buf)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < META_WAYLAND_DMA_BUF_MAX_FDS; i++)
|
||||
{
|
||||
int fd = dma_buf->fds[i];
|
||||
|
||||
if (fd < 0)
|
||||
break;
|
||||
|
||||
if (meta_wayland_dma_buf_fd_readable (fd))
|
||||
continue;
|
||||
|
||||
if (!source)
|
||||
{
|
||||
source =
|
||||
(MetaWaylandDmaBufSource *) g_source_new (&meta_wayland_dma_buf_source_funcs,
|
||||
sizeof (*source));
|
||||
source->buffer = g_object_ref (buffer);
|
||||
source->dispatch = dispatch;
|
||||
source->user_data = user_data;
|
||||
}
|
||||
|
||||
source->fd_tags[i] = g_source_add_unix_fd (&source->base, fd, G_IO_IN);
|
||||
}
|
||||
|
||||
if (!source)
|
||||
return NULL;
|
||||
|
||||
return &source->base;
|
||||
}
|
||||
|
||||
static void
|
||||
buffer_params_create_common (struct wl_client *client,
|
||||
struct wl_resource *params_resource,
|
||||
|
@ -57,6 +57,14 @@ meta_wayland_dma_buf_fds_for_wayland_buffer (MetaWaylandBuffer *buffer);
|
||||
MetaWaylandDmaBufBuffer *
|
||||
meta_wayland_dma_buf_from_buffer (MetaWaylandBuffer *buffer);
|
||||
|
||||
typedef void (*MetaWaylandDmaBufSourceDispatch) (MetaWaylandBuffer *buffer,
|
||||
gpointer user_data);
|
||||
|
||||
GSource *
|
||||
meta_wayland_dma_buf_create_source (MetaWaylandBuffer *buffer,
|
||||
MetaWaylandDmaBufSourceDispatch dispatch,
|
||||
gpointer user_data);
|
||||
|
||||
CoglScanout *
|
||||
meta_wayland_dma_buf_try_acquire_scanout (MetaWaylandDmaBufBuffer *dma_buf,
|
||||
CoglOnscreen *onscreen);
|
||||
|
Loading…
Reference in New Issue
Block a user