diff options
author | Michel Dänzer <mdaenzer@redhat.com> | 2022-06-10 16:40:10 +0200 |
---|---|---|
committer | Michel Dänzer <michel@daenzer.net> | 2022-12-01 09:40:38 +0100 |
commit | d43150573e08bfe94ae7c78a2515808d874553b7 (patch) | |
tree | 4b19100674bc7d5643f84dadf40ee13493e07383 | |
parent | 416285d1b7a3e74bb3a7f5b9d0a35aa7e8a59801 (diff) | |
download | mutter-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.c | 147 | ||||
-rw-r--r-- | src/wayland/meta-wayland-dma-buf.h | 8 |
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); |