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 "wayland/meta-wayland-transaction.h"
|
||||||
|
|
||||||
|
#include <glib-unix.h>
|
||||||
|
|
||||||
#include "wayland/meta-wayland.h"
|
#include "wayland/meta-wayland.h"
|
||||||
|
#include "wayland/meta-wayland-dma-buf.h"
|
||||||
|
|
||||||
#define META_WAYLAND_TRANSACTION_NONE ((void *)(uintptr_t) G_MAXSIZE)
|
#define META_WAYLAND_TRANSACTION_NONE ((void *)(uintptr_t) G_MAXSIZE)
|
||||||
|
|
||||||
@ -39,6 +42,9 @@ struct _MetaWaylandTransaction
|
|||||||
* Values: Pointer to MetaWaylandTransactionEntry for the surface
|
* Values: Pointer to MetaWaylandTransactionEntry for the surface
|
||||||
*/
|
*/
|
||||||
GHashTable *entries;
|
GHashTable *entries;
|
||||||
|
|
||||||
|
/* Sources for buffers which are not ready yet */
|
||||||
|
GHashTable *buf_sources;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _MetaWaylandTransactionEntry
|
struct _MetaWaylandTransactionEntry
|
||||||
@ -161,6 +167,9 @@ meta_wayland_transaction_apply (MetaWaylandTransaction *transaction,
|
|||||||
MetaWaylandTransactionEntry *entry;
|
MetaWaylandTransactionEntry *entry;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (g_hash_table_size (transaction->entries) == 0)
|
||||||
|
goto free;
|
||||||
|
|
||||||
surfaces = (MetaWaylandSurface **)
|
surfaces = (MetaWaylandSurface **)
|
||||||
g_hash_table_get_keys_as_array (transaction->entries, &num_surfaces);
|
g_hash_table_get_keys_as_array (transaction->entries, &num_surfaces);
|
||||||
states = g_new (MetaWaylandSurfaceState *, 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]);
|
meta_wayland_transaction_sync_child_states (surfaces[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free:
|
||||||
meta_wayland_transaction_free (transaction);
|
meta_wayland_transaction_free (transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
has_unapplied_dependencies (MetaWaylandTransaction *transaction)
|
has_dependencies (MetaWaylandTransaction *transaction)
|
||||||
{
|
{
|
||||||
GHashTableIter iter;
|
GHashTableIter iter;
|
||||||
MetaWaylandSurface *surface;
|
MetaWaylandSurface *surface;
|
||||||
|
|
||||||
|
if (transaction->buf_sources &&
|
||||||
|
g_hash_table_size (transaction->buf_sources) > 0)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
g_hash_table_iter_init (&iter, transaction->entries);
|
g_hash_table_iter_init (&iter, transaction->entries);
|
||||||
while (g_hash_table_iter_next (&iter, (gpointer *) &surface, NULL))
|
while (g_hash_table_iter_next (&iter, (gpointer *) &surface, NULL))
|
||||||
{
|
{
|
||||||
@ -237,7 +251,7 @@ static void
|
|||||||
meta_wayland_transaction_maybe_apply_one (MetaWaylandTransaction *transaction,
|
meta_wayland_transaction_maybe_apply_one (MetaWaylandTransaction *transaction,
|
||||||
MetaWaylandTransaction **first_candidate)
|
MetaWaylandTransaction **first_candidate)
|
||||||
{
|
{
|
||||||
if (has_unapplied_dependencies (transaction))
|
if (has_dependencies (transaction))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
meta_wayland_transaction_apply (transaction, first_candidate);
|
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
|
void
|
||||||
meta_wayland_transaction_commit (MetaWaylandTransaction *transaction)
|
meta_wayland_transaction_commit (MetaWaylandTransaction *transaction)
|
||||||
{
|
{
|
||||||
@ -269,6 +326,21 @@ meta_wayland_transaction_commit (MetaWaylandTransaction *transaction)
|
|||||||
gboolean maybe_apply = TRUE;
|
gboolean maybe_apply = TRUE;
|
||||||
GHashTableIter iter;
|
GHashTableIter iter;
|
||||||
MetaWaylandSurface *surface;
|
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->committed_sequence = ++committed_sequence;
|
||||||
transaction->node.data = transaction;
|
transaction->node.data = transaction;
|
||||||
@ -504,6 +576,7 @@ meta_wayland_transaction_free (MetaWaylandTransaction *transaction)
|
|||||||
g_queue_unlink (committed_queue, &transaction->node);
|
g_queue_unlink (committed_queue, &transaction->node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_clear_pointer (&transaction->buf_sources, g_hash_table_destroy);
|
||||||
g_hash_table_destroy (transaction->entries);
|
g_hash_table_destroy (transaction->entries);
|
||||||
g_free (transaction);
|
g_free (transaction);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user