mirror of
https://github.com/brl/mutter.git
synced 2024-11-26 10:00:45 -05:00
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>
This commit is contained in:
parent
b7599fb766
commit
6e6a38342e
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user