diff options
author | Michel Dänzer <mdaenzer@redhat.com> | 2022-06-10 18:49:29 +0200 |
---|---|---|
committer | Michel Dänzer <michel@daenzer.net> | 2022-12-01 16:35:19 +0100 |
commit | 6e6a38342e651b3a64db8a242ce291c4e704e00e (patch) | |
tree | b31d7e2edb9856649cf1d7f00d8684571e803dcd | |
parent | b7599fb766832d0ed14b91414672ecf15582198a (diff) | |
download | mutter-6e6a38342e651b3a64db8a242ce291c4e704e00e.tar.gz |
wayland/surface: Defer meta_wayland_transaction_apply for dma-bufs
Until all dma-buf file descriptors for all buffers in the transaction
are readable, which corresponds to when the client drawing to the
buffers has finished.
This fixes https://gitlab.gnome.org/GNOME/mutter/-/issues/1162 if the
GPU & drivers support high priority contexts which can preempt lower
priority contexts.
v2:
* Also remove dma-buf fds from transaction and try applying it from
pending_buffer_resource_destroyed. Avoids freeze due to leaving a
GSource based on a closed fd attached if a client destroys a wl_buffer
which is part of a transaction which was committed but not applied
yet. (Robert Mader)
* Tweak transaction cleanup logic in wl_surface_destructor.
v3:
* Adapt to meta_wayland_dma_buf_get_source.
v4:
* Adapt to new commits using transactions for (sub-)surface destruction,
drop code to remove destroyed surfaces from pending transactions.
v5:
* Use g_clear_pointer in meta_wayland_transaction_destroy.
(Georges Basile Stavracas Neto)
* Add spaces between type casts and values. (Carlos Garnacho)
* Use (gpointer *) instead of (void**). (Carlos Garnacho)
* Use gpointer instead of void * in
meta_wayland_transaction_dma_buf_dispatch.
v6:
* Use g_hash_table_remove in meta_wayland_transaction_dma_buf_dispatch.
(Carlos Garnacho)
v7: (Jonas Ådahl)
* Move include of glib-unix.h below that of meta-wayland-transaction.h.
* Split up g_hash_table_iter_next call to multiple lines in
meta_wayland_transaction_commit.
* Call g_source_destroy as well as g_source_unref when freeing a
committed but not yet applied transaction (during mutter shutdown).
v8:
* Drop dma_buf_source_destroy, can use g_source_destroy directly.
(Jonas Ådahl)
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
-rw-r--r-- | src/wayland/meta-wayland-transaction.c | 77 |
1 files changed, 75 insertions, 2 deletions
diff --git a/src/wayland/meta-wayland-transaction.c b/src/wayland/meta-wayland-transaction.c index 6bf0376e9..5ca4cf87d 100644 --- a/src/wayland/meta-wayland-transaction.c +++ b/src/wayland/meta-wayland-transaction.c @@ -23,7 +23,10 @@ #include "wayland/meta-wayland-transaction.h" +#include <glib-unix.h> + #include "wayland/meta-wayland.h" +#include "wayland/meta-wayland-dma-buf.h" #define META_WAYLAND_TRANSACTION_NONE ((void *)(uintptr_t) G_MAXSIZE) @@ -39,6 +42,9 @@ struct _MetaWaylandTransaction * Values: Pointer to MetaWaylandTransactionEntry for the surface */ GHashTable *entries; + + /* Sources for buffers which are not ready yet */ + GHashTable *buf_sources; }; struct _MetaWaylandTransactionEntry @@ -161,6 +167,9 @@ meta_wayland_transaction_apply (MetaWaylandTransaction *transaction, MetaWaylandTransactionEntry *entry; int i; + if (g_hash_table_size (transaction->entries) == 0) + goto free; + surfaces = (MetaWaylandSurface **) g_hash_table_get_keys_as_array (transaction->entries, &num_surfaces); states = g_new (MetaWaylandSurfaceState *, num_surfaces); @@ -214,15 +223,20 @@ meta_wayland_transaction_apply (MetaWaylandTransaction *transaction, meta_wayland_transaction_sync_child_states (surfaces[i]); } +free: meta_wayland_transaction_free (transaction); } static gboolean -has_unapplied_dependencies (MetaWaylandTransaction *transaction) +has_dependencies (MetaWaylandTransaction *transaction) { GHashTableIter iter; MetaWaylandSurface *surface; + if (transaction->buf_sources && + g_hash_table_size (transaction->buf_sources) > 0) + return TRUE; + g_hash_table_iter_init (&iter, transaction->entries); while (g_hash_table_iter_next (&iter, (gpointer *) &surface, NULL)) { @@ -237,7 +251,7 @@ static void meta_wayland_transaction_maybe_apply_one (MetaWaylandTransaction *transaction, MetaWaylandTransaction **first_candidate) { - if (has_unapplied_dependencies (transaction)) + if (has_dependencies (transaction)) return; meta_wayland_transaction_apply (transaction, first_candidate); @@ -261,6 +275,49 @@ meta_wayland_transaction_maybe_apply (MetaWaylandTransaction *transaction) } } +static void +meta_wayland_transaction_dma_buf_dispatch (MetaWaylandBuffer *buffer, + gpointer user_data) +{ + MetaWaylandTransaction *transaction = user_data; + + if (!transaction->buf_sources || + !g_hash_table_remove (transaction->buf_sources, buffer)) + return; + + meta_wayland_transaction_maybe_apply (transaction); +} + +static gboolean +meta_wayland_transaction_add_dma_buf_source (MetaWaylandTransaction *transaction, + MetaWaylandBuffer *buffer) +{ + GSource *source; + + if (transaction->buf_sources && + g_hash_table_contains (transaction->buf_sources, buffer)) + return FALSE; + + source = meta_wayland_dma_buf_create_source (buffer, + meta_wayland_transaction_dma_buf_dispatch, + transaction); + if (!source) + return FALSE; + + if (!transaction->buf_sources) + { + transaction->buf_sources = + g_hash_table_new_full (NULL, NULL, NULL, + (GDestroyNotify) g_source_destroy); + } + + g_hash_table_insert (transaction->buf_sources, buffer, source); + g_source_attach (source, NULL); + g_source_unref (source); + + return TRUE; +} + void meta_wayland_transaction_commit (MetaWaylandTransaction *transaction) { @@ -269,6 +326,21 @@ meta_wayland_transaction_commit (MetaWaylandTransaction *transaction) gboolean maybe_apply = TRUE; GHashTableIter iter; MetaWaylandSurface *surface; + MetaWaylandTransactionEntry *entry; + + g_hash_table_iter_init (&iter, transaction->entries); + while (g_hash_table_iter_next (&iter, + (gpointer *) &surface, (gpointer *) &entry)) + { + if (entry && entry->state) + { + MetaWaylandBuffer *buffer = entry->state->buffer; + + if (buffer && + meta_wayland_transaction_add_dma_buf_source (transaction, buffer)) + maybe_apply = FALSE; + } + } transaction->committed_sequence = ++committed_sequence; transaction->node.data = transaction; @@ -504,6 +576,7 @@ meta_wayland_transaction_free (MetaWaylandTransaction *transaction) g_queue_unlink (committed_queue, &transaction->node); } + g_clear_pointer (&transaction->buf_sources, g_hash_table_destroy); g_hash_table_destroy (transaction->entries); g_free (transaction); } |