summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichel Dänzer <mdaenzer@redhat.com>2022-06-10 16:40:10 +0200
committerMichel Dänzer <michel@daenzer.net>2022-12-01 09:40:38 +0100
commitd43150573e08bfe94ae7c78a2515808d874553b7 (patch)
tree4b19100674bc7d5643f84dadf40ee13493e07383
parent416285d1b7a3e74bb3a7f5b9d0a35aa7e8a59801 (diff)
downloadmutter-d43150573e08bfe94ae7c78a2515808d874553b7.tar.gz
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>
-rw-r--r--src/wayland/meta-wayland-dma-buf.c147
-rw-r--r--src/wayland/meta-wayland-dma-buf.h8
2 files changed, 155 insertions, 0 deletions
diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c
index cc74afad5..05e812eca 100644
--- a/src/wayland/meta-wayland-dma-buf.c
+++ b/src/wayland/meta-wayland-dma-buf.c
@@ -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,
diff --git a/src/wayland/meta-wayland-dma-buf.h b/src/wayland/meta-wayland-dma-buf.h
index 57b1ef68e..716b8c778 100644
--- a/src/wayland/meta-wayland-dma-buf.h
+++ b/src/wayland/meta-wayland-dma-buf.h
@@ -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);