mutter/src/wayland/meta-wayland-transaction.c

651 lines
19 KiB
C
Raw Normal View History

/*
* Wayland Transaction Support
*
* Copyright (C) 2021 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "wayland/meta-wayland-transaction.h"
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>
2022-06-10 18:49:29 +02:00
#include <glib-unix.h>
wayland/surface: Make sure transactions are applied in consistent order If multiple transactions have entries for the same surface, they are applied in the same order as they were committed. Otherwise, they can be applied in any order. This is preparation for following changes, transactions are still applied as soon as they're committed. v2: * Move GQueue for transactions to MetaWaylandCompositor (Jonas Ådahl) v3 * Say "entry for" instead of "state for", since there can be transaction entries with no state (for surfaces which are getting destroyed). v4: * Use a hash table to keep track of all candidate transactions which might be newly ready to be applied. * Use clearer function / variable names. v5: * Use custom single-linked list instead of hash table for candidate transactions, ordered by the transaction commit sequence number, so that they're attempted to be applied in the same order as they were committed. * Rename transaction->queue to transaction->committed_queue, and simplify its handling. v6: (Carlos Garnacho) * Add spaces between type casts and values. * Use (gpointer *) instead of (void**). v7: (Jonas Ådahl) * Use G_MAXSIZE instead of ULONG_MAX. * Fix indentation of meta_wayland_transaction_apply & meta_wayland_transaction_maybe_apply_one parameters. * Refactor find_next_transaction_for_surface & ensure_next_candidate helper functions out of meta_wayland_transaction_apply. * Refactor has_unapplied_dependencies helper function out of meta_wayland_transaction_maybe_apply_one. * Make while (TRUE) loop in meta_wayland_transaction_maybe_apply consistent with general usage. * Drop unused value local from meta_wayland_transaction_commit. * Store pointer to compositor object in transactions, instead of pointer to the queue of committed transactions. * Drop tautological g_assert from meta_wayland_transaction_apply. (me) Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2021-05-30 15:00:13 +02:00
#include "wayland/meta-wayland.h"
wayland/surface: Overhaul handling of buffer use count Move the use count from a separate MetaWaylandBufferRef struct to the MetaWaylandBuffer class, and remove the former. The buffer use count is now incremented already in meta_wayland_surface_commit, since the Wayland protocol defines the buffer to be in use by the compositor at that point. If the buffer attachment ends up being dropped again before it is applied to the surface state (e.g. because another buffer is committed to a synchronized sub-surface before the parent surface is committed), the use count is now decremented, and a buffer release event is sent if the use count drops to 0. Buffer release events were previously incorrectly not sent under these circumstances. Test case: Run the weston-subsurfaces demo with the -r1 and/or -t1 command line parameter. Resize the window. Before this change, weston-subsurfaces would freeze or abort after a few resize operations, because mutter failed to send release events and the client ran out of usable buffers. v2: * Handle NULL priv->buffer_ref in meta_wayland_cursor_surface_apply_state. v3: * Remove MetaWaylandBufferRef altogether, move the use count tracking to MetaWaylandBuffer itself. Much simpler, and doesn't run into lifetime issues when mutter shuts down. v4: * Warn if use count isn't 0 in meta_wayland_buffer_finalize. * Keep pending_buffer_resource_destroyed for attached but not yet committed buffers. If the client attaches a buffer and then destroys it before commit, we ignore the buffer attachement, same as before this MR. v5: * Rebase on top of new commit which splits up surface->texture. * MetaWaylandSurfaceState::buffer can only be non-NULL if ::newly_attached is TRUE, simplify accordingly. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2022-06-22 18:43:11 +02:00
#include "wayland/meta-wayland-buffer.h"
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>
2022-06-10 18:49:29 +02:00
#include "wayland/meta-wayland-dma-buf.h"
wayland/surface: Make sure transactions are applied in consistent order If multiple transactions have entries for the same surface, they are applied in the same order as they were committed. Otherwise, they can be applied in any order. This is preparation for following changes, transactions are still applied as soon as they're committed. v2: * Move GQueue for transactions to MetaWaylandCompositor (Jonas Ådahl) v3 * Say "entry for" instead of "state for", since there can be transaction entries with no state (for surfaces which are getting destroyed). v4: * Use a hash table to keep track of all candidate transactions which might be newly ready to be applied. * Use clearer function / variable names. v5: * Use custom single-linked list instead of hash table for candidate transactions, ordered by the transaction commit sequence number, so that they're attempted to be applied in the same order as they were committed. * Rename transaction->queue to transaction->committed_queue, and simplify its handling. v6: (Carlos Garnacho) * Add spaces between type casts and values. * Use (gpointer *) instead of (void**). v7: (Jonas Ådahl) * Use G_MAXSIZE instead of ULONG_MAX. * Fix indentation of meta_wayland_transaction_apply & meta_wayland_transaction_maybe_apply_one parameters. * Refactor find_next_transaction_for_surface & ensure_next_candidate helper functions out of meta_wayland_transaction_apply. * Refactor has_unapplied_dependencies helper function out of meta_wayland_transaction_maybe_apply_one. * Make while (TRUE) loop in meta_wayland_transaction_maybe_apply consistent with general usage. * Drop unused value local from meta_wayland_transaction_commit. * Store pointer to compositor object in transactions, instead of pointer to the queue of committed transactions. * Drop tautological g_assert from meta_wayland_transaction_apply. (me) Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2021-05-30 15:00:13 +02:00
#define META_WAYLAND_TRANSACTION_NONE ((void *)(uintptr_t) G_MAXSIZE)
struct _MetaWaylandTransaction
{
wayland/surface: Make sure transactions are applied in consistent order If multiple transactions have entries for the same surface, they are applied in the same order as they were committed. Otherwise, they can be applied in any order. This is preparation for following changes, transactions are still applied as soon as they're committed. v2: * Move GQueue for transactions to MetaWaylandCompositor (Jonas Ådahl) v3 * Say "entry for" instead of "state for", since there can be transaction entries with no state (for surfaces which are getting destroyed). v4: * Use a hash table to keep track of all candidate transactions which might be newly ready to be applied. * Use clearer function / variable names. v5: * Use custom single-linked list instead of hash table for candidate transactions, ordered by the transaction commit sequence number, so that they're attempted to be applied in the same order as they were committed. * Rename transaction->queue to transaction->committed_queue, and simplify its handling. v6: (Carlos Garnacho) * Add spaces between type casts and values. * Use (gpointer *) instead of (void**). v7: (Jonas Ådahl) * Use G_MAXSIZE instead of ULONG_MAX. * Fix indentation of meta_wayland_transaction_apply & meta_wayland_transaction_maybe_apply_one parameters. * Refactor find_next_transaction_for_surface & ensure_next_candidate helper functions out of meta_wayland_transaction_apply. * Refactor has_unapplied_dependencies helper function out of meta_wayland_transaction_maybe_apply_one. * Make while (TRUE) loop in meta_wayland_transaction_maybe_apply consistent with general usage. * Drop unused value local from meta_wayland_transaction_commit. * Store pointer to compositor object in transactions, instead of pointer to the queue of committed transactions. * Drop tautological g_assert from meta_wayland_transaction_apply. (me) Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2021-05-30 15:00:13 +02:00
GList node;
MetaWaylandCompositor *compositor;
MetaWaylandTransaction *next_candidate;
uint64_t committed_sequence;
/*
* Keys: All surfaces referenced in the transaction
* Values: Pointer to MetaWaylandTransactionEntry for the surface
*/
GHashTable *entries;
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>
2022-06-10 18:49:29 +02:00
/* Sources for buffers which are not ready yet */
GHashTable *buf_sources;
};
struct _MetaWaylandTransactionEntry
{
/* Next committed transaction with entry for the same surface */
MetaWaylandTransaction *next_transaction;
MetaWaylandSurfaceState *state;
/* Sub-surface position */
gboolean has_sub_pos;
int x;
int y;
};
static MetaWaylandTransactionEntry *
meta_wayland_transaction_get_entry (MetaWaylandTransaction *transaction,
MetaWaylandSurface *surface)
{
return g_hash_table_lookup (transaction->entries, surface);
}
static void
meta_wayland_transaction_sync_child_states (MetaWaylandSurface *surface)
{
MetaWaylandSurface *subsurface_surface;
MetaWaylandSubsurface *subsurface;
MetaWaylandActorSurface *actor_surface;
META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (&surface->applied_state, subsurface_surface)
{
subsurface = META_WAYLAND_SUBSURFACE (subsurface_surface->role);
actor_surface = META_WAYLAND_ACTOR_SURFACE (subsurface);
meta_wayland_actor_surface_sync_actor_state (actor_surface);
}
if (!surface->applied_state.parent &&
surface->role && META_IS_WAYLAND_SUBSURFACE (surface->role))
{
/* Unmapped sub-surface */
subsurface = META_WAYLAND_SUBSURFACE (surface->role);
actor_surface = META_WAYLAND_ACTOR_SURFACE (subsurface);
meta_wayland_actor_surface_sync_actor_state (actor_surface);
}
}
static void
meta_wayland_transaction_apply_subsurface_position (MetaWaylandSurface *surface,
MetaWaylandTransactionEntry *entry)
{
if (!entry->has_sub_pos)
return;
surface->sub.x = entry->x;
surface->sub.y = entry->y;
}
void
meta_wayland_transaction_drop_subsurface_state (MetaWaylandTransaction *transaction,
MetaWaylandSurface *surface)
{
MetaWaylandSurface *parent = surface->committed_state.parent;
MetaWaylandTransactionEntry *entry;
entry = meta_wayland_transaction_get_entry (transaction, surface);
if (entry)
entry->has_sub_pos = FALSE;
if (!parent)
return;
entry = meta_wayland_transaction_get_entry (transaction, parent);
if (entry && entry->state && entry->state->subsurface_placement_ops)
meta_wayland_subsurface_drop_placement_ops (entry->state, surface);
}
static gboolean
is_ancestor (MetaWaylandSurface *candidate,
MetaWaylandSurface *reference)
{
MetaWaylandSurface *ancestor;
for (ancestor = reference->applied_state.parent;
wayland/surface: Use transactions for all sub-surface hierarchy changes And keep track of the hierarchy separately for the Wayland protocol and for output. Protocol state is updated immediately as protocol requests are processed, output state only when the corresponding transaction is applied (which may be deferred until the next commit of the parent surface). v2: * Directly add placement ops to a transaction, instead of going via pending_state. * Use transaction entry for the sub-surface instead of that for its parent surface. v3: * Use transaction entry for the parent surface again, to ensure proper ordering of placement ops, and call meta_wayland_surface_notify_subsurface_state_changed only once per parent surface. * Drop all use of wl_resource_add_destroy_listener, transactions are keeping surfaces alive as long as needed. v4: * Rebase on https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2501 * Drop ClutterActor code from meta_wayland_surface_apply_placement_ops. (Robert Mader) v5: * Rename MetaWaylandSubSurfaceState to MetaWaylandSurfaceSubState, since the next commit adds not sub-surface specific state to it. v6: * Move include of meta-wayland-subsurface.h from meta-wayland-transaction.c to .h, since the latter references MetaWaylandSubsurfacePlacementOp. v7: * Drop superfluous !entry check from meta_wayland_transaction_apply. v8: * Rename output/protocol fields to output/protocol_state. (Jonas Ådahl) v9: * Use meta_wayland_surface_state_new in meta_wayland_transaction_add_placement_op. v10: * Fix a few style issues per check-style.py. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2021-07-23 16:01:37 +02:00
ancestor;
ancestor = ancestor->applied_state.parent)
{
if (ancestor == candidate)
return TRUE;
}
return FALSE;
}
static int
meta_wayland_transaction_compare (const void *key1,
const void *key2)
{
MetaWaylandSurface *surface1 = *(MetaWaylandSurface **) key1;
MetaWaylandSurface *surface2 = *(MetaWaylandSurface **) key2;
/* Order of siblings doesn't matter */
if (surface1->applied_state.parent == surface2->applied_state.parent)
return 0;
/* Ancestor surfaces come before descendant surfaces */
if (is_ancestor (surface1, surface2))
return 1;
if (is_ancestor (surface2, surface1))
return -1;
/*
* Order unrelated surfaces by their toplevel surface pointer values, to
* prevent unrelated surfaces from getting mixed between siblings
*/
return (meta_wayland_surface_get_toplevel (surface1) <
meta_wayland_surface_get_toplevel (surface2)) ? -1 : 1;
}
wayland/surface: Make sure transactions are applied in consistent order If multiple transactions have entries for the same surface, they are applied in the same order as they were committed. Otherwise, they can be applied in any order. This is preparation for following changes, transactions are still applied as soon as they're committed. v2: * Move GQueue for transactions to MetaWaylandCompositor (Jonas Ådahl) v3 * Say "entry for" instead of "state for", since there can be transaction entries with no state (for surfaces which are getting destroyed). v4: * Use a hash table to keep track of all candidate transactions which might be newly ready to be applied. * Use clearer function / variable names. v5: * Use custom single-linked list instead of hash table for candidate transactions, ordered by the transaction commit sequence number, so that they're attempted to be applied in the same order as they were committed. * Rename transaction->queue to transaction->committed_queue, and simplify its handling. v6: (Carlos Garnacho) * Add spaces between type casts and values. * Use (gpointer *) instead of (void**). v7: (Jonas Ådahl) * Use G_MAXSIZE instead of ULONG_MAX. * Fix indentation of meta_wayland_transaction_apply & meta_wayland_transaction_maybe_apply_one parameters. * Refactor find_next_transaction_for_surface & ensure_next_candidate helper functions out of meta_wayland_transaction_apply. * Refactor has_unapplied_dependencies helper function out of meta_wayland_transaction_maybe_apply_one. * Make while (TRUE) loop in meta_wayland_transaction_maybe_apply consistent with general usage. * Drop unused value local from meta_wayland_transaction_commit. * Store pointer to compositor object in transactions, instead of pointer to the queue of committed transactions. * Drop tautological g_assert from meta_wayland_transaction_apply. (me) Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2021-05-30 15:00:13 +02:00
static void
ensure_next_candidate (MetaWaylandTransaction *transaction,
MetaWaylandTransaction **first_candidate)
{
MetaWaylandTransaction **candidate;
if (transaction->next_candidate)
return;
candidate = first_candidate;
while (*candidate != META_WAYLAND_TRANSACTION_NONE &&
(*candidate)->committed_sequence <
transaction->committed_sequence)
candidate = &(*candidate)->next_candidate;
transaction->next_candidate = *candidate;
*candidate = transaction;
}
static void
meta_wayland_transaction_apply (MetaWaylandTransaction *transaction,
MetaWaylandTransaction **first_candidate)
{
g_autofree MetaWaylandSurface **surfaces = NULL;
g_autofree MetaWaylandSurfaceState **states = NULL;
unsigned int num_surfaces;
wayland/surface: Use transactions for all sub-surface hierarchy changes And keep track of the hierarchy separately for the Wayland protocol and for output. Protocol state is updated immediately as protocol requests are processed, output state only when the corresponding transaction is applied (which may be deferred until the next commit of the parent surface). v2: * Directly add placement ops to a transaction, instead of going via pending_state. * Use transaction entry for the sub-surface instead of that for its parent surface. v3: * Use transaction entry for the parent surface again, to ensure proper ordering of placement ops, and call meta_wayland_surface_notify_subsurface_state_changed only once per parent surface. * Drop all use of wl_resource_add_destroy_listener, transactions are keeping surfaces alive as long as needed. v4: * Rebase on https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2501 * Drop ClutterActor code from meta_wayland_surface_apply_placement_ops. (Robert Mader) v5: * Rename MetaWaylandSubSurfaceState to MetaWaylandSurfaceSubState, since the next commit adds not sub-surface specific state to it. v6: * Move include of meta-wayland-subsurface.h from meta-wayland-transaction.c to .h, since the latter references MetaWaylandSubsurfacePlacementOp. v7: * Drop superfluous !entry check from meta_wayland_transaction_apply. v8: * Rename output/protocol fields to output/protocol_state. (Jonas Ådahl) v9: * Use meta_wayland_surface_state_new in meta_wayland_transaction_add_placement_op. v10: * Fix a few style issues per check-style.py. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2021-07-23 16:01:37 +02:00
MetaWaylandSurface *surface;
MetaWaylandTransactionEntry *entry;
int i;
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>
2022-06-10 18:49:29 +02:00
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);
wayland/surface: Use transactions for all sub-surface hierarchy changes And keep track of the hierarchy separately for the Wayland protocol and for output. Protocol state is updated immediately as protocol requests are processed, output state only when the corresponding transaction is applied (which may be deferred until the next commit of the parent surface). v2: * Directly add placement ops to a transaction, instead of going via pending_state. * Use transaction entry for the sub-surface instead of that for its parent surface. v3: * Use transaction entry for the parent surface again, to ensure proper ordering of placement ops, and call meta_wayland_surface_notify_subsurface_state_changed only once per parent surface. * Drop all use of wl_resource_add_destroy_listener, transactions are keeping surfaces alive as long as needed. v4: * Rebase on https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2501 * Drop ClutterActor code from meta_wayland_surface_apply_placement_ops. (Robert Mader) v5: * Rename MetaWaylandSubSurfaceState to MetaWaylandSurfaceSubState, since the next commit adds not sub-surface specific state to it. v6: * Move include of meta-wayland-subsurface.h from meta-wayland-transaction.c to .h, since the latter references MetaWaylandSubsurfacePlacementOp. v7: * Drop superfluous !entry check from meta_wayland_transaction_apply. v8: * Rename output/protocol fields to output/protocol_state. (Jonas Ådahl) v9: * Use meta_wayland_surface_state_new in meta_wayland_transaction_add_placement_op. v10: * Fix a few style issues per check-style.py. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2021-07-23 16:01:37 +02:00
/* Apply sub-surface states to ensure output surface hierarchy is up to date */
for (i = 0; i < num_surfaces; i++)
{
surface = surfaces[i];
entry = meta_wayland_transaction_get_entry (transaction, surface);
meta_wayland_transaction_apply_subsurface_position (surface, entry);
if (entry->state && entry->state->subsurface_placement_ops)
meta_wayland_surface_apply_placement_ops (surface, entry->state);
}
/* Sort surfaces from ancestors to descendants */
qsort (surfaces, num_surfaces, sizeof (MetaWaylandSurface *),
meta_wayland_transaction_compare);
/* Apply states from ancestors to descendants */
for (i = 0; i < num_surfaces; i++)
{
wayland/surface: Use transactions for all sub-surface hierarchy changes And keep track of the hierarchy separately for the Wayland protocol and for output. Protocol state is updated immediately as protocol requests are processed, output state only when the corresponding transaction is applied (which may be deferred until the next commit of the parent surface). v2: * Directly add placement ops to a transaction, instead of going via pending_state. * Use transaction entry for the sub-surface instead of that for its parent surface. v3: * Use transaction entry for the parent surface again, to ensure proper ordering of placement ops, and call meta_wayland_surface_notify_subsurface_state_changed only once per parent surface. * Drop all use of wl_resource_add_destroy_listener, transactions are keeping surfaces alive as long as needed. v4: * Rebase on https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2501 * Drop ClutterActor code from meta_wayland_surface_apply_placement_ops. (Robert Mader) v5: * Rename MetaWaylandSubSurfaceState to MetaWaylandSurfaceSubState, since the next commit adds not sub-surface specific state to it. v6: * Move include of meta-wayland-subsurface.h from meta-wayland-transaction.c to .h, since the latter references MetaWaylandSubsurfacePlacementOp. v7: * Drop superfluous !entry check from meta_wayland_transaction_apply. v8: * Rename output/protocol fields to output/protocol_state. (Jonas Ådahl) v9: * Use meta_wayland_surface_state_new in meta_wayland_transaction_add_placement_op. v10: * Fix a few style issues per check-style.py. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2021-07-23 16:01:37 +02:00
surface = surfaces[i];
entry = meta_wayland_transaction_get_entry (transaction, surface);
wayland/surface: Use transactions for all sub-surface hierarchy changes And keep track of the hierarchy separately for the Wayland protocol and for output. Protocol state is updated immediately as protocol requests are processed, output state only when the corresponding transaction is applied (which may be deferred until the next commit of the parent surface). v2: * Directly add placement ops to a transaction, instead of going via pending_state. * Use transaction entry for the sub-surface instead of that for its parent surface. v3: * Use transaction entry for the parent surface again, to ensure proper ordering of placement ops, and call meta_wayland_surface_notify_subsurface_state_changed only once per parent surface. * Drop all use of wl_resource_add_destroy_listener, transactions are keeping surfaces alive as long as needed. v4: * Rebase on https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2501 * Drop ClutterActor code from meta_wayland_surface_apply_placement_ops. (Robert Mader) v5: * Rename MetaWaylandSubSurfaceState to MetaWaylandSurfaceSubState, since the next commit adds not sub-surface specific state to it. v6: * Move include of meta-wayland-subsurface.h from meta-wayland-transaction.c to .h, since the latter references MetaWaylandSubsurfacePlacementOp. v7: * Drop superfluous !entry check from meta_wayland_transaction_apply. v8: * Rename output/protocol fields to output/protocol_state. (Jonas Ådahl) v9: * Use meta_wayland_surface_state_new in meta_wayland_transaction_add_placement_op. v10: * Fix a few style issues per check-style.py. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2021-07-23 16:01:37 +02:00
states[i] = entry->state;
if (entry->state)
meta_wayland_surface_apply_state (surface, entry->state);
wayland/surface: Make sure transactions are applied in consistent order If multiple transactions have entries for the same surface, they are applied in the same order as they were committed. Otherwise, they can be applied in any order. This is preparation for following changes, transactions are still applied as soon as they're committed. v2: * Move GQueue for transactions to MetaWaylandCompositor (Jonas Ådahl) v3 * Say "entry for" instead of "state for", since there can be transaction entries with no state (for surfaces which are getting destroyed). v4: * Use a hash table to keep track of all candidate transactions which might be newly ready to be applied. * Use clearer function / variable names. v5: * Use custom single-linked list instead of hash table for candidate transactions, ordered by the transaction commit sequence number, so that they're attempted to be applied in the same order as they were committed. * Rename transaction->queue to transaction->committed_queue, and simplify its handling. v6: (Carlos Garnacho) * Add spaces between type casts and values. * Use (gpointer *) instead of (void**). v7: (Jonas Ådahl) * Use G_MAXSIZE instead of ULONG_MAX. * Fix indentation of meta_wayland_transaction_apply & meta_wayland_transaction_maybe_apply_one parameters. * Refactor find_next_transaction_for_surface & ensure_next_candidate helper functions out of meta_wayland_transaction_apply. * Refactor has_unapplied_dependencies helper function out of meta_wayland_transaction_maybe_apply_one. * Make while (TRUE) loop in meta_wayland_transaction_maybe_apply consistent with general usage. * Drop unused value local from meta_wayland_transaction_commit. * Store pointer to compositor object in transactions, instead of pointer to the queue of committed transactions. * Drop tautological g_assert from meta_wayland_transaction_apply. (me) Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2021-05-30 15:00:13 +02:00
if (surface->transaction.last_committed == transaction)
{
surface->transaction.first_committed = NULL;
surface->transaction.last_committed = NULL;
}
else
{
MetaWaylandTransaction *next_transaction = entry->next_transaction;
wayland/surface: Make sure transactions are applied in consistent order If multiple transactions have entries for the same surface, they are applied in the same order as they were committed. Otherwise, they can be applied in any order. This is preparation for following changes, transactions are still applied as soon as they're committed. v2: * Move GQueue for transactions to MetaWaylandCompositor (Jonas Ådahl) v3 * Say "entry for" instead of "state for", since there can be transaction entries with no state (for surfaces which are getting destroyed). v4: * Use a hash table to keep track of all candidate transactions which might be newly ready to be applied. * Use clearer function / variable names. v5: * Use custom single-linked list instead of hash table for candidate transactions, ordered by the transaction commit sequence number, so that they're attempted to be applied in the same order as they were committed. * Rename transaction->queue to transaction->committed_queue, and simplify its handling. v6: (Carlos Garnacho) * Add spaces between type casts and values. * Use (gpointer *) instead of (void**). v7: (Jonas Ådahl) * Use G_MAXSIZE instead of ULONG_MAX. * Fix indentation of meta_wayland_transaction_apply & meta_wayland_transaction_maybe_apply_one parameters. * Refactor find_next_transaction_for_surface & ensure_next_candidate helper functions out of meta_wayland_transaction_apply. * Refactor has_unapplied_dependencies helper function out of meta_wayland_transaction_maybe_apply_one. * Make while (TRUE) loop in meta_wayland_transaction_maybe_apply consistent with general usage. * Drop unused value local from meta_wayland_transaction_commit. * Store pointer to compositor object in transactions, instead of pointer to the queue of committed transactions. * Drop tautological g_assert from meta_wayland_transaction_apply. (me) Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2021-05-30 15:00:13 +02:00
if (next_transaction)
{
surface->transaction.first_committed = next_transaction;
ensure_next_candidate (next_transaction, first_candidate);
}
}
}
/* Synchronize child states from descendants to ancestors */
for (i = num_surfaces - 1; i >= 0; i--)
{
if (states[i])
meta_wayland_transaction_sync_child_states (surfaces[i]);
}
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>
2022-06-10 18:49:29 +02:00
free:
meta_wayland_transaction_free (transaction);
}
wayland/surface: Make sure transactions are applied in consistent order If multiple transactions have entries for the same surface, they are applied in the same order as they were committed. Otherwise, they can be applied in any order. This is preparation for following changes, transactions are still applied as soon as they're committed. v2: * Move GQueue for transactions to MetaWaylandCompositor (Jonas Ådahl) v3 * Say "entry for" instead of "state for", since there can be transaction entries with no state (for surfaces which are getting destroyed). v4: * Use a hash table to keep track of all candidate transactions which might be newly ready to be applied. * Use clearer function / variable names. v5: * Use custom single-linked list instead of hash table for candidate transactions, ordered by the transaction commit sequence number, so that they're attempted to be applied in the same order as they were committed. * Rename transaction->queue to transaction->committed_queue, and simplify its handling. v6: (Carlos Garnacho) * Add spaces between type casts and values. * Use (gpointer *) instead of (void**). v7: (Jonas Ådahl) * Use G_MAXSIZE instead of ULONG_MAX. * Fix indentation of meta_wayland_transaction_apply & meta_wayland_transaction_maybe_apply_one parameters. * Refactor find_next_transaction_for_surface & ensure_next_candidate helper functions out of meta_wayland_transaction_apply. * Refactor has_unapplied_dependencies helper function out of meta_wayland_transaction_maybe_apply_one. * Make while (TRUE) loop in meta_wayland_transaction_maybe_apply consistent with general usage. * Drop unused value local from meta_wayland_transaction_commit. * Store pointer to compositor object in transactions, instead of pointer to the queue of committed transactions. * Drop tautological g_assert from meta_wayland_transaction_apply. (me) Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2021-05-30 15:00:13 +02:00
static gboolean
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>
2022-06-10 18:49:29 +02:00
has_dependencies (MetaWaylandTransaction *transaction)
wayland/surface: Make sure transactions are applied in consistent order If multiple transactions have entries for the same surface, they are applied in the same order as they were committed. Otherwise, they can be applied in any order. This is preparation for following changes, transactions are still applied as soon as they're committed. v2: * Move GQueue for transactions to MetaWaylandCompositor (Jonas Ådahl) v3 * Say "entry for" instead of "state for", since there can be transaction entries with no state (for surfaces which are getting destroyed). v4: * Use a hash table to keep track of all candidate transactions which might be newly ready to be applied. * Use clearer function / variable names. v5: * Use custom single-linked list instead of hash table for candidate transactions, ordered by the transaction commit sequence number, so that they're attempted to be applied in the same order as they were committed. * Rename transaction->queue to transaction->committed_queue, and simplify its handling. v6: (Carlos Garnacho) * Add spaces between type casts and values. * Use (gpointer *) instead of (void**). v7: (Jonas Ådahl) * Use G_MAXSIZE instead of ULONG_MAX. * Fix indentation of meta_wayland_transaction_apply & meta_wayland_transaction_maybe_apply_one parameters. * Refactor find_next_transaction_for_surface & ensure_next_candidate helper functions out of meta_wayland_transaction_apply. * Refactor has_unapplied_dependencies helper function out of meta_wayland_transaction_maybe_apply_one. * Make while (TRUE) loop in meta_wayland_transaction_maybe_apply consistent with general usage. * Drop unused value local from meta_wayland_transaction_commit. * Store pointer to compositor object in transactions, instead of pointer to the queue of committed transactions. * Drop tautological g_assert from meta_wayland_transaction_apply. (me) Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2021-05-30 15:00:13 +02:00
{
GHashTableIter iter;
MetaWaylandSurface *surface;
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>
2022-06-10 18:49:29 +02:00
if (transaction->buf_sources &&
g_hash_table_size (transaction->buf_sources) > 0)
return TRUE;
wayland/surface: Make sure transactions are applied in consistent order If multiple transactions have entries for the same surface, they are applied in the same order as they were committed. Otherwise, they can be applied in any order. This is preparation for following changes, transactions are still applied as soon as they're committed. v2: * Move GQueue for transactions to MetaWaylandCompositor (Jonas Ådahl) v3 * Say "entry for" instead of "state for", since there can be transaction entries with no state (for surfaces which are getting destroyed). v4: * Use a hash table to keep track of all candidate transactions which might be newly ready to be applied. * Use clearer function / variable names. v5: * Use custom single-linked list instead of hash table for candidate transactions, ordered by the transaction commit sequence number, so that they're attempted to be applied in the same order as they were committed. * Rename transaction->queue to transaction->committed_queue, and simplify its handling. v6: (Carlos Garnacho) * Add spaces between type casts and values. * Use (gpointer *) instead of (void**). v7: (Jonas Ådahl) * Use G_MAXSIZE instead of ULONG_MAX. * Fix indentation of meta_wayland_transaction_apply & meta_wayland_transaction_maybe_apply_one parameters. * Refactor find_next_transaction_for_surface & ensure_next_candidate helper functions out of meta_wayland_transaction_apply. * Refactor has_unapplied_dependencies helper function out of meta_wayland_transaction_maybe_apply_one. * Make while (TRUE) loop in meta_wayland_transaction_maybe_apply consistent with general usage. * Drop unused value local from meta_wayland_transaction_commit. * Store pointer to compositor object in transactions, instead of pointer to the queue of committed transactions. * Drop tautological g_assert from meta_wayland_transaction_apply. (me) Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2021-05-30 15:00:13 +02:00
g_hash_table_iter_init (&iter, transaction->entries);
while (g_hash_table_iter_next (&iter, (gpointer *) &surface, NULL))
{
if (surface->transaction.first_committed != transaction)
return TRUE;
}
return FALSE;
}
static void
meta_wayland_transaction_maybe_apply_one (MetaWaylandTransaction *transaction,
MetaWaylandTransaction **first_candidate)
{
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>
2022-06-10 18:49:29 +02:00
if (has_dependencies (transaction))
wayland/surface: Make sure transactions are applied in consistent order If multiple transactions have entries for the same surface, they are applied in the same order as they were committed. Otherwise, they can be applied in any order. This is preparation for following changes, transactions are still applied as soon as they're committed. v2: * Move GQueue for transactions to MetaWaylandCompositor (Jonas Ådahl) v3 * Say "entry for" instead of "state for", since there can be transaction entries with no state (for surfaces which are getting destroyed). v4: * Use a hash table to keep track of all candidate transactions which might be newly ready to be applied. * Use clearer function / variable names. v5: * Use custom single-linked list instead of hash table for candidate transactions, ordered by the transaction commit sequence number, so that they're attempted to be applied in the same order as they were committed. * Rename transaction->queue to transaction->committed_queue, and simplify its handling. v6: (Carlos Garnacho) * Add spaces between type casts and values. * Use (gpointer *) instead of (void**). v7: (Jonas Ådahl) * Use G_MAXSIZE instead of ULONG_MAX. * Fix indentation of meta_wayland_transaction_apply & meta_wayland_transaction_maybe_apply_one parameters. * Refactor find_next_transaction_for_surface & ensure_next_candidate helper functions out of meta_wayland_transaction_apply. * Refactor has_unapplied_dependencies helper function out of meta_wayland_transaction_maybe_apply_one. * Make while (TRUE) loop in meta_wayland_transaction_maybe_apply consistent with general usage. * Drop unused value local from meta_wayland_transaction_commit. * Store pointer to compositor object in transactions, instead of pointer to the queue of committed transactions. * Drop tautological g_assert from meta_wayland_transaction_apply. (me) Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2021-05-30 15:00:13 +02:00
return;
meta_wayland_transaction_apply (transaction, first_candidate);
}
static void
meta_wayland_transaction_maybe_apply (MetaWaylandTransaction *transaction)
{
MetaWaylandTransaction *first_candidate = META_WAYLAND_TRANSACTION_NONE;
while (TRUE)
{
meta_wayland_transaction_maybe_apply_one (transaction, &first_candidate);
if (first_candidate == META_WAYLAND_TRANSACTION_NONE)
return;
transaction = first_candidate;
first_candidate = transaction->next_candidate;
transaction->next_candidate = NULL;
}
}
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>
2022-06-10 18:49:29 +02:00
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;
}
static void
meta_wayland_transaction_add_placement_surfaces (MetaWaylandTransaction *transaction,
MetaWaylandSurfaceState *state)
{
GSList *l;
for (l = state->subsurface_placement_ops; l; l = l->next)
{
MetaWaylandSubsurfacePlacementOp *op = l->data;
meta_wayland_transaction_ensure_entry (transaction, op->surface);
if (op->sibling)
meta_wayland_transaction_ensure_entry (transaction, op->sibling);
}
}
wayland/surface: Make sure transactions are applied in consistent order If multiple transactions have entries for the same surface, they are applied in the same order as they were committed. Otherwise, they can be applied in any order. This is preparation for following changes, transactions are still applied as soon as they're committed. v2: * Move GQueue for transactions to MetaWaylandCompositor (Jonas Ådahl) v3 * Say "entry for" instead of "state for", since there can be transaction entries with no state (for surfaces which are getting destroyed). v4: * Use a hash table to keep track of all candidate transactions which might be newly ready to be applied. * Use clearer function / variable names. v5: * Use custom single-linked list instead of hash table for candidate transactions, ordered by the transaction commit sequence number, so that they're attempted to be applied in the same order as they were committed. * Rename transaction->queue to transaction->committed_queue, and simplify its handling. v6: (Carlos Garnacho) * Add spaces between type casts and values. * Use (gpointer *) instead of (void**). v7: (Jonas Ådahl) * Use G_MAXSIZE instead of ULONG_MAX. * Fix indentation of meta_wayland_transaction_apply & meta_wayland_transaction_maybe_apply_one parameters. * Refactor find_next_transaction_for_surface & ensure_next_candidate helper functions out of meta_wayland_transaction_apply. * Refactor has_unapplied_dependencies helper function out of meta_wayland_transaction_maybe_apply_one. * Make while (TRUE) loop in meta_wayland_transaction_maybe_apply consistent with general usage. * Drop unused value local from meta_wayland_transaction_commit. * Store pointer to compositor object in transactions, instead of pointer to the queue of committed transactions. * Drop tautological g_assert from meta_wayland_transaction_apply. (me) Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2021-05-30 15:00:13 +02:00
void
meta_wayland_transaction_commit (MetaWaylandTransaction *transaction)
{
static uint64_t committed_sequence;
GQueue *committed_queue;
gboolean maybe_apply = TRUE;
GHashTableIter iter;
MetaWaylandSurface *surface;
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>
2022-06-10 18:49:29 +02:00
MetaWaylandTransactionEntry *entry;
g_autoptr (GPtrArray) placement_states = NULL;
unsigned int num_placement_states = 0;
int i;
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>
2022-06-10 18:49:29 +02:00
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;
if (entry->state->subsurface_placement_ops)
{
if (!placement_states)
placement_states = g_ptr_array_new ();
g_ptr_array_add (placement_states, entry->state);
num_placement_states++;
}
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>
2022-06-10 18:49:29 +02:00
}
}
wayland/surface: Make sure transactions are applied in consistent order If multiple transactions have entries for the same surface, they are applied in the same order as they were committed. Otherwise, they can be applied in any order. This is preparation for following changes, transactions are still applied as soon as they're committed. v2: * Move GQueue for transactions to MetaWaylandCompositor (Jonas Ådahl) v3 * Say "entry for" instead of "state for", since there can be transaction entries with no state (for surfaces which are getting destroyed). v4: * Use a hash table to keep track of all candidate transactions which might be newly ready to be applied. * Use clearer function / variable names. v5: * Use custom single-linked list instead of hash table for candidate transactions, ordered by the transaction commit sequence number, so that they're attempted to be applied in the same order as they were committed. * Rename transaction->queue to transaction->committed_queue, and simplify its handling. v6: (Carlos Garnacho) * Add spaces between type casts and values. * Use (gpointer *) instead of (void**). v7: (Jonas Ådahl) * Use G_MAXSIZE instead of ULONG_MAX. * Fix indentation of meta_wayland_transaction_apply & meta_wayland_transaction_maybe_apply_one parameters. * Refactor find_next_transaction_for_surface & ensure_next_candidate helper functions out of meta_wayland_transaction_apply. * Refactor has_unapplied_dependencies helper function out of meta_wayland_transaction_maybe_apply_one. * Make while (TRUE) loop in meta_wayland_transaction_maybe_apply consistent with general usage. * Drop unused value local from meta_wayland_transaction_commit. * Store pointer to compositor object in transactions, instead of pointer to the queue of committed transactions. * Drop tautological g_assert from meta_wayland_transaction_apply. (me) Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2021-05-30 15:00:13 +02:00
for (i = 0; i < num_placement_states; i++)
{
MetaWaylandSurfaceState *placement_state;
placement_state = g_ptr_array_index (placement_states, i);
meta_wayland_transaction_add_placement_surfaces (transaction,
placement_state);
}
wayland/surface: Make sure transactions are applied in consistent order If multiple transactions have entries for the same surface, they are applied in the same order as they were committed. Otherwise, they can be applied in any order. This is preparation for following changes, transactions are still applied as soon as they're committed. v2: * Move GQueue for transactions to MetaWaylandCompositor (Jonas Ådahl) v3 * Say "entry for" instead of "state for", since there can be transaction entries with no state (for surfaces which are getting destroyed). v4: * Use a hash table to keep track of all candidate transactions which might be newly ready to be applied. * Use clearer function / variable names. v5: * Use custom single-linked list instead of hash table for candidate transactions, ordered by the transaction commit sequence number, so that they're attempted to be applied in the same order as they were committed. * Rename transaction->queue to transaction->committed_queue, and simplify its handling. v6: (Carlos Garnacho) * Add spaces between type casts and values. * Use (gpointer *) instead of (void**). v7: (Jonas Ådahl) * Use G_MAXSIZE instead of ULONG_MAX. * Fix indentation of meta_wayland_transaction_apply & meta_wayland_transaction_maybe_apply_one parameters. * Refactor find_next_transaction_for_surface & ensure_next_candidate helper functions out of meta_wayland_transaction_apply. * Refactor has_unapplied_dependencies helper function out of meta_wayland_transaction_maybe_apply_one. * Make while (TRUE) loop in meta_wayland_transaction_maybe_apply consistent with general usage. * Drop unused value local from meta_wayland_transaction_commit. * Store pointer to compositor object in transactions, instead of pointer to the queue of committed transactions. * Drop tautological g_assert from meta_wayland_transaction_apply. (me) Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2021-05-30 15:00:13 +02:00
transaction->committed_sequence = ++committed_sequence;
transaction->node.data = transaction;
committed_queue =
meta_wayland_compositor_get_committed_transactions (transaction->compositor);
g_queue_push_tail_link (committed_queue, &transaction->node);
g_hash_table_iter_init (&iter, transaction->entries);
while (g_hash_table_iter_next (&iter, (gpointer *) &surface, NULL))
{
if (surface->transaction.first_committed)
{
MetaWaylandTransactionEntry *entry;
wayland/surface: Make sure transactions are applied in consistent order If multiple transactions have entries for the same surface, they are applied in the same order as they were committed. Otherwise, they can be applied in any order. This is preparation for following changes, transactions are still applied as soon as they're committed. v2: * Move GQueue for transactions to MetaWaylandCompositor (Jonas Ådahl) v3 * Say "entry for" instead of "state for", since there can be transaction entries with no state (for surfaces which are getting destroyed). v4: * Use a hash table to keep track of all candidate transactions which might be newly ready to be applied. * Use clearer function / variable names. v5: * Use custom single-linked list instead of hash table for candidate transactions, ordered by the transaction commit sequence number, so that they're attempted to be applied in the same order as they were committed. * Rename transaction->queue to transaction->committed_queue, and simplify its handling. v6: (Carlos Garnacho) * Add spaces between type casts and values. * Use (gpointer *) instead of (void**). v7: (Jonas Ådahl) * Use G_MAXSIZE instead of ULONG_MAX. * Fix indentation of meta_wayland_transaction_apply & meta_wayland_transaction_maybe_apply_one parameters. * Refactor find_next_transaction_for_surface & ensure_next_candidate helper functions out of meta_wayland_transaction_apply. * Refactor has_unapplied_dependencies helper function out of meta_wayland_transaction_maybe_apply_one. * Make while (TRUE) loop in meta_wayland_transaction_maybe_apply consistent with general usage. * Drop unused value local from meta_wayland_transaction_commit. * Store pointer to compositor object in transactions, instead of pointer to the queue of committed transactions. * Drop tautological g_assert from meta_wayland_transaction_apply. (me) Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2021-05-30 15:00:13 +02:00
entry = g_hash_table_lookup (surface->transaction.last_committed->entries,
surface);
entry->next_transaction = transaction;
maybe_apply = FALSE;
}
wayland/surface: Make sure transactions are applied in consistent order If multiple transactions have entries for the same surface, they are applied in the same order as they were committed. Otherwise, they can be applied in any order. This is preparation for following changes, transactions are still applied as soon as they're committed. v2: * Move GQueue for transactions to MetaWaylandCompositor (Jonas Ådahl) v3 * Say "entry for" instead of "state for", since there can be transaction entries with no state (for surfaces which are getting destroyed). v4: * Use a hash table to keep track of all candidate transactions which might be newly ready to be applied. * Use clearer function / variable names. v5: * Use custom single-linked list instead of hash table for candidate transactions, ordered by the transaction commit sequence number, so that they're attempted to be applied in the same order as they were committed. * Rename transaction->queue to transaction->committed_queue, and simplify its handling. v6: (Carlos Garnacho) * Add spaces between type casts and values. * Use (gpointer *) instead of (void**). v7: (Jonas Ådahl) * Use G_MAXSIZE instead of ULONG_MAX. * Fix indentation of meta_wayland_transaction_apply & meta_wayland_transaction_maybe_apply_one parameters. * Refactor find_next_transaction_for_surface & ensure_next_candidate helper functions out of meta_wayland_transaction_apply. * Refactor has_unapplied_dependencies helper function out of meta_wayland_transaction_maybe_apply_one. * Make while (TRUE) loop in meta_wayland_transaction_maybe_apply consistent with general usage. * Drop unused value local from meta_wayland_transaction_commit. * Store pointer to compositor object in transactions, instead of pointer to the queue of committed transactions. * Drop tautological g_assert from meta_wayland_transaction_apply. (me) Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2021-05-30 15:00:13 +02:00
else
{
surface->transaction.first_committed = transaction;
}
surface->transaction.last_committed = transaction;
wayland/surface: Make sure transactions are applied in consistent order If multiple transactions have entries for the same surface, they are applied in the same order as they were committed. Otherwise, they can be applied in any order. This is preparation for following changes, transactions are still applied as soon as they're committed. v2: * Move GQueue for transactions to MetaWaylandCompositor (Jonas Ådahl) v3 * Say "entry for" instead of "state for", since there can be transaction entries with no state (for surfaces which are getting destroyed). v4: * Use a hash table to keep track of all candidate transactions which might be newly ready to be applied. * Use clearer function / variable names. v5: * Use custom single-linked list instead of hash table for candidate transactions, ordered by the transaction commit sequence number, so that they're attempted to be applied in the same order as they were committed. * Rename transaction->queue to transaction->committed_queue, and simplify its handling. v6: (Carlos Garnacho) * Add spaces between type casts and values. * Use (gpointer *) instead of (void**). v7: (Jonas Ådahl) * Use G_MAXSIZE instead of ULONG_MAX. * Fix indentation of meta_wayland_transaction_apply & meta_wayland_transaction_maybe_apply_one parameters. * Refactor find_next_transaction_for_surface & ensure_next_candidate helper functions out of meta_wayland_transaction_apply. * Refactor has_unapplied_dependencies helper function out of meta_wayland_transaction_maybe_apply_one. * Make while (TRUE) loop in meta_wayland_transaction_maybe_apply consistent with general usage. * Drop unused value local from meta_wayland_transaction_commit. * Store pointer to compositor object in transactions, instead of pointer to the queue of committed transactions. * Drop tautological g_assert from meta_wayland_transaction_apply. (me) Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2021-05-30 15:00:13 +02:00
}
if (maybe_apply)
meta_wayland_transaction_maybe_apply (transaction);
}
MetaWaylandTransactionEntry *
meta_wayland_transaction_ensure_entry (MetaWaylandTransaction *transaction,
MetaWaylandSurface *surface)
{
MetaWaylandTransactionEntry *entry;
entry = meta_wayland_transaction_get_entry (transaction, surface);
if (entry)
return entry;
entry = g_new0 (MetaWaylandTransactionEntry, 1);
g_hash_table_insert (transaction->entries, g_object_ref (surface), entry);
return entry;
}
static void
meta_wayland_transaction_entry_free (MetaWaylandTransactionEntry *entry)
{
wayland/surface: Overhaul handling of buffer use count Move the use count from a separate MetaWaylandBufferRef struct to the MetaWaylandBuffer class, and remove the former. The buffer use count is now incremented already in meta_wayland_surface_commit, since the Wayland protocol defines the buffer to be in use by the compositor at that point. If the buffer attachment ends up being dropped again before it is applied to the surface state (e.g. because another buffer is committed to a synchronized sub-surface before the parent surface is committed), the use count is now decremented, and a buffer release event is sent if the use count drops to 0. Buffer release events were previously incorrectly not sent under these circumstances. Test case: Run the weston-subsurfaces demo with the -r1 and/or -t1 command line parameter. Resize the window. Before this change, weston-subsurfaces would freeze or abort after a few resize operations, because mutter failed to send release events and the client ran out of usable buffers. v2: * Handle NULL priv->buffer_ref in meta_wayland_cursor_surface_apply_state. v3: * Remove MetaWaylandBufferRef altogether, move the use count tracking to MetaWaylandBuffer itself. Much simpler, and doesn't run into lifetime issues when mutter shuts down. v4: * Warn if use count isn't 0 in meta_wayland_buffer_finalize. * Keep pending_buffer_resource_destroyed for attached but not yet committed buffers. If the client attaches a buffer and then destroys it before commit, we ignore the buffer attachement, same as before this MR. v5: * Rebase on top of new commit which splits up surface->texture. * MetaWaylandSurfaceState::buffer can only be non-NULL if ::newly_attached is TRUE, simplify accordingly. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2022-06-22 18:43:11 +02:00
if (entry->state)
{
if (entry->state->buffer)
meta_wayland_buffer_dec_use_count (entry->state->buffer);
g_clear_object (&entry->state);
}
g_free (entry);
}
wayland/surface: Use transactions for all sub-surface hierarchy changes And keep track of the hierarchy separately for the Wayland protocol and for output. Protocol state is updated immediately as protocol requests are processed, output state only when the corresponding transaction is applied (which may be deferred until the next commit of the parent surface). v2: * Directly add placement ops to a transaction, instead of going via pending_state. * Use transaction entry for the sub-surface instead of that for its parent surface. v3: * Use transaction entry for the parent surface again, to ensure proper ordering of placement ops, and call meta_wayland_surface_notify_subsurface_state_changed only once per parent surface. * Drop all use of wl_resource_add_destroy_listener, transactions are keeping surfaces alive as long as needed. v4: * Rebase on https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2501 * Drop ClutterActor code from meta_wayland_surface_apply_placement_ops. (Robert Mader) v5: * Rename MetaWaylandSubSurfaceState to MetaWaylandSurfaceSubState, since the next commit adds not sub-surface specific state to it. v6: * Move include of meta-wayland-subsurface.h from meta-wayland-transaction.c to .h, since the latter references MetaWaylandSubsurfacePlacementOp. v7: * Drop superfluous !entry check from meta_wayland_transaction_apply. v8: * Rename output/protocol fields to output/protocol_state. (Jonas Ådahl) v9: * Use meta_wayland_surface_state_new in meta_wayland_transaction_add_placement_op. v10: * Fix a few style issues per check-style.py. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2021-07-23 16:01:37 +02:00
void
meta_wayland_transaction_add_placement_op (MetaWaylandTransaction *transaction,
MetaWaylandSurface *surface,
MetaWaylandSubsurfacePlacementOp *op)
{
MetaWaylandTransactionEntry *entry;
MetaWaylandSurfaceState *state;
entry = meta_wayland_transaction_ensure_entry (transaction, surface);
if (!entry->state)
entry->state = meta_wayland_surface_state_new ();
state = entry->state;
state->subsurface_placement_ops =
g_slist_append (state->subsurface_placement_ops, op);
}
void
meta_wayland_transaction_add_subsurface_position (MetaWaylandTransaction *transaction,
MetaWaylandSurface *surface,
int x,
int y)
{
MetaWaylandTransactionEntry *entry;
entry = meta_wayland_transaction_ensure_entry (transaction, surface);
entry->x = x;
entry->y = y;
entry->has_sub_pos = TRUE;
}
void
meta_wayland_transaction_add_xdg_popup_reposition (MetaWaylandTransaction *transaction,
MetaWaylandSurface *surface,
void *xdg_positioner,
uint32_t token)
{
MetaWaylandTransactionEntry *entry;
MetaWaylandSurfaceState *state;
entry = meta_wayland_transaction_ensure_entry (transaction, surface);
if (entry->state)
g_clear_pointer (&entry->state->xdg_positioner, g_free);
else
entry->state = meta_wayland_surface_state_new ();
state = entry->state;
state->xdg_positioner = xdg_positioner;
state->xdg_popup_reposition_token = token;
}
static void
meta_wayland_transaction_entry_merge_into (MetaWaylandTransactionEntry *from,
MetaWaylandTransactionEntry *to)
{
if (from->has_sub_pos)
{
to->x = from->x;
to->y = from->y;
to->has_sub_pos = TRUE;
}
if (from->state)
{
if (to->state)
{
meta_wayland_surface_state_merge_into (from->state, to->state);
g_clear_object (&from->state);
}
else
{
to->state = g_steal_pointer (&from->state);
}
}
}
void
meta_wayland_transaction_merge_into (MetaWaylandTransaction *from,
MetaWaylandTransaction *to)
{
GHashTableIter iter;
MetaWaylandSurface *surface;
MetaWaylandTransactionEntry *from_entry, *to_entry;
g_hash_table_iter_init (&iter, from->entries);
while (g_hash_table_iter_next (&iter, (gpointer *) &surface,
(gpointer *) &from_entry))
{
to_entry = meta_wayland_transaction_get_entry (to, surface);
if (!to_entry)
{
g_hash_table_iter_steal (&iter);
g_hash_table_insert (to->entries, surface, from_entry);
continue;
}
meta_wayland_transaction_entry_merge_into (from_entry, to_entry);
g_hash_table_iter_remove (&iter);
}
meta_wayland_transaction_free (from);
}
void
meta_wayland_transaction_merge_pending_state (MetaWaylandTransaction *transaction,
MetaWaylandSurface *surface)
{
MetaWaylandSurfaceState *pending = surface->pending_state;
MetaWaylandTransactionEntry *entry;
entry = meta_wayland_transaction_ensure_entry (transaction, surface);
if (!entry->state)
{
entry->state = pending;
surface->pending_state = meta_wayland_surface_state_new ();
return;
}
meta_wayland_surface_state_merge_into (pending, entry->state);
meta_wayland_surface_state_reset (pending);
}
MetaWaylandTransaction *
wayland/surface: Make sure transactions are applied in consistent order If multiple transactions have entries for the same surface, they are applied in the same order as they were committed. Otherwise, they can be applied in any order. This is preparation for following changes, transactions are still applied as soon as they're committed. v2: * Move GQueue for transactions to MetaWaylandCompositor (Jonas Ådahl) v3 * Say "entry for" instead of "state for", since there can be transaction entries with no state (for surfaces which are getting destroyed). v4: * Use a hash table to keep track of all candidate transactions which might be newly ready to be applied. * Use clearer function / variable names. v5: * Use custom single-linked list instead of hash table for candidate transactions, ordered by the transaction commit sequence number, so that they're attempted to be applied in the same order as they were committed. * Rename transaction->queue to transaction->committed_queue, and simplify its handling. v6: (Carlos Garnacho) * Add spaces between type casts and values. * Use (gpointer *) instead of (void**). v7: (Jonas Ådahl) * Use G_MAXSIZE instead of ULONG_MAX. * Fix indentation of meta_wayland_transaction_apply & meta_wayland_transaction_maybe_apply_one parameters. * Refactor find_next_transaction_for_surface & ensure_next_candidate helper functions out of meta_wayland_transaction_apply. * Refactor has_unapplied_dependencies helper function out of meta_wayland_transaction_maybe_apply_one. * Make while (TRUE) loop in meta_wayland_transaction_maybe_apply consistent with general usage. * Drop unused value local from meta_wayland_transaction_commit. * Store pointer to compositor object in transactions, instead of pointer to the queue of committed transactions. * Drop tautological g_assert from meta_wayland_transaction_apply. (me) Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2021-05-30 15:00:13 +02:00
meta_wayland_transaction_new (MetaWaylandCompositor *compositor)
{
MetaWaylandTransaction *transaction;
transaction = g_new0 (MetaWaylandTransaction, 1);
wayland/surface: Make sure transactions are applied in consistent order If multiple transactions have entries for the same surface, they are applied in the same order as they were committed. Otherwise, they can be applied in any order. This is preparation for following changes, transactions are still applied as soon as they're committed. v2: * Move GQueue for transactions to MetaWaylandCompositor (Jonas Ådahl) v3 * Say "entry for" instead of "state for", since there can be transaction entries with no state (for surfaces which are getting destroyed). v4: * Use a hash table to keep track of all candidate transactions which might be newly ready to be applied. * Use clearer function / variable names. v5: * Use custom single-linked list instead of hash table for candidate transactions, ordered by the transaction commit sequence number, so that they're attempted to be applied in the same order as they were committed. * Rename transaction->queue to transaction->committed_queue, and simplify its handling. v6: (Carlos Garnacho) * Add spaces between type casts and values. * Use (gpointer *) instead of (void**). v7: (Jonas Ådahl) * Use G_MAXSIZE instead of ULONG_MAX. * Fix indentation of meta_wayland_transaction_apply & meta_wayland_transaction_maybe_apply_one parameters. * Refactor find_next_transaction_for_surface & ensure_next_candidate helper functions out of meta_wayland_transaction_apply. * Refactor has_unapplied_dependencies helper function out of meta_wayland_transaction_maybe_apply_one. * Make while (TRUE) loop in meta_wayland_transaction_maybe_apply consistent with general usage. * Drop unused value local from meta_wayland_transaction_commit. * Store pointer to compositor object in transactions, instead of pointer to the queue of committed transactions. * Drop tautological g_assert from meta_wayland_transaction_apply. (me) Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2021-05-30 15:00:13 +02:00
transaction->compositor = compositor;
transaction->entries = g_hash_table_new_full (NULL, NULL, g_object_unref,
(GDestroyNotify) meta_wayland_transaction_entry_free);
return transaction;
}
void
meta_wayland_transaction_free (MetaWaylandTransaction *transaction)
{
wayland/surface: Make sure transactions are applied in consistent order If multiple transactions have entries for the same surface, they are applied in the same order as they were committed. Otherwise, they can be applied in any order. This is preparation for following changes, transactions are still applied as soon as they're committed. v2: * Move GQueue for transactions to MetaWaylandCompositor (Jonas Ådahl) v3 * Say "entry for" instead of "state for", since there can be transaction entries with no state (for surfaces which are getting destroyed). v4: * Use a hash table to keep track of all candidate transactions which might be newly ready to be applied. * Use clearer function / variable names. v5: * Use custom single-linked list instead of hash table for candidate transactions, ordered by the transaction commit sequence number, so that they're attempted to be applied in the same order as they were committed. * Rename transaction->queue to transaction->committed_queue, and simplify its handling. v6: (Carlos Garnacho) * Add spaces between type casts and values. * Use (gpointer *) instead of (void**). v7: (Jonas Ådahl) * Use G_MAXSIZE instead of ULONG_MAX. * Fix indentation of meta_wayland_transaction_apply & meta_wayland_transaction_maybe_apply_one parameters. * Refactor find_next_transaction_for_surface & ensure_next_candidate helper functions out of meta_wayland_transaction_apply. * Refactor has_unapplied_dependencies helper function out of meta_wayland_transaction_maybe_apply_one. * Make while (TRUE) loop in meta_wayland_transaction_maybe_apply consistent with general usage. * Drop unused value local from meta_wayland_transaction_commit. * Store pointer to compositor object in transactions, instead of pointer to the queue of committed transactions. * Drop tautological g_assert from meta_wayland_transaction_apply. (me) Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2021-05-30 15:00:13 +02:00
if (transaction->node.data)
{
GQueue *committed_queue =
meta_wayland_compositor_get_committed_transactions (transaction->compositor);
g_queue_unlink (committed_queue, &transaction->node);
}
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>
2022-06-10 18:49:29 +02:00
g_clear_pointer (&transaction->buf_sources, g_hash_table_destroy);
g_hash_table_destroy (transaction->entries);
g_free (transaction);
}
wayland/surface: Make sure transactions are applied in consistent order If multiple transactions have entries for the same surface, they are applied in the same order as they were committed. Otherwise, they can be applied in any order. This is preparation for following changes, transactions are still applied as soon as they're committed. v2: * Move GQueue for transactions to MetaWaylandCompositor (Jonas Ådahl) v3 * Say "entry for" instead of "state for", since there can be transaction entries with no state (for surfaces which are getting destroyed). v4: * Use a hash table to keep track of all candidate transactions which might be newly ready to be applied. * Use clearer function / variable names. v5: * Use custom single-linked list instead of hash table for candidate transactions, ordered by the transaction commit sequence number, so that they're attempted to be applied in the same order as they were committed. * Rename transaction->queue to transaction->committed_queue, and simplify its handling. v6: (Carlos Garnacho) * Add spaces between type casts and values. * Use (gpointer *) instead of (void**). v7: (Jonas Ådahl) * Use G_MAXSIZE instead of ULONG_MAX. * Fix indentation of meta_wayland_transaction_apply & meta_wayland_transaction_maybe_apply_one parameters. * Refactor find_next_transaction_for_surface & ensure_next_candidate helper functions out of meta_wayland_transaction_apply. * Refactor has_unapplied_dependencies helper function out of meta_wayland_transaction_maybe_apply_one. * Make while (TRUE) loop in meta_wayland_transaction_maybe_apply consistent with general usage. * Drop unused value local from meta_wayland_transaction_commit. * Store pointer to compositor object in transactions, instead of pointer to the queue of committed transactions. * Drop tautological g_assert from meta_wayland_transaction_apply. (me) Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2021-05-30 15:00:13 +02:00
void
meta_wayland_transaction_finalize (MetaWaylandCompositor *compositor)
{
GQueue *transactions;
GList *node;
wayland/surface: Make sure transactions are applied in consistent order If multiple transactions have entries for the same surface, they are applied in the same order as they were committed. Otherwise, they can be applied in any order. This is preparation for following changes, transactions are still applied as soon as they're committed. v2: * Move GQueue for transactions to MetaWaylandCompositor (Jonas Ådahl) v3 * Say "entry for" instead of "state for", since there can be transaction entries with no state (for surfaces which are getting destroyed). v4: * Use a hash table to keep track of all candidate transactions which might be newly ready to be applied. * Use clearer function / variable names. v5: * Use custom single-linked list instead of hash table for candidate transactions, ordered by the transaction commit sequence number, so that they're attempted to be applied in the same order as they were committed. * Rename transaction->queue to transaction->committed_queue, and simplify its handling. v6: (Carlos Garnacho) * Add spaces between type casts and values. * Use (gpointer *) instead of (void**). v7: (Jonas Ådahl) * Use G_MAXSIZE instead of ULONG_MAX. * Fix indentation of meta_wayland_transaction_apply & meta_wayland_transaction_maybe_apply_one parameters. * Refactor find_next_transaction_for_surface & ensure_next_candidate helper functions out of meta_wayland_transaction_apply. * Refactor has_unapplied_dependencies helper function out of meta_wayland_transaction_maybe_apply_one. * Make while (TRUE) loop in meta_wayland_transaction_maybe_apply consistent with general usage. * Drop unused value local from meta_wayland_transaction_commit. * Store pointer to compositor object in transactions, instead of pointer to the queue of committed transactions. * Drop tautological g_assert from meta_wayland_transaction_apply. (me) Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2021-05-30 15:00:13 +02:00
transactions = meta_wayland_compositor_get_committed_transactions (compositor);
while ((node = g_queue_pop_head_link (transactions)))
{
MetaWaylandTransaction *transaction = node->data;
g_assert (node == &transaction->node);
meta_wayland_transaction_free (transaction);
}
wayland/surface: Make sure transactions are applied in consistent order If multiple transactions have entries for the same surface, they are applied in the same order as they were committed. Otherwise, they can be applied in any order. This is preparation for following changes, transactions are still applied as soon as they're committed. v2: * Move GQueue for transactions to MetaWaylandCompositor (Jonas Ådahl) v3 * Say "entry for" instead of "state for", since there can be transaction entries with no state (for surfaces which are getting destroyed). v4: * Use a hash table to keep track of all candidate transactions which might be newly ready to be applied. * Use clearer function / variable names. v5: * Use custom single-linked list instead of hash table for candidate transactions, ordered by the transaction commit sequence number, so that they're attempted to be applied in the same order as they were committed. * Rename transaction->queue to transaction->committed_queue, and simplify its handling. v6: (Carlos Garnacho) * Add spaces between type casts and values. * Use (gpointer *) instead of (void**). v7: (Jonas Ådahl) * Use G_MAXSIZE instead of ULONG_MAX. * Fix indentation of meta_wayland_transaction_apply & meta_wayland_transaction_maybe_apply_one parameters. * Refactor find_next_transaction_for_surface & ensure_next_candidate helper functions out of meta_wayland_transaction_apply. * Refactor has_unapplied_dependencies helper function out of meta_wayland_transaction_maybe_apply_one. * Make while (TRUE) loop in meta_wayland_transaction_maybe_apply consistent with general usage. * Drop unused value local from meta_wayland_transaction_commit. * Store pointer to compositor object in transactions, instead of pointer to the queue of committed transactions. * Drop tautological g_assert from meta_wayland_transaction_apply. (me) Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
2021-05-30 15:00:13 +02:00
}
void
meta_wayland_transaction_init (MetaWaylandCompositor *compositor)
{
GQueue *transactions;
transactions = meta_wayland_compositor_get_committed_transactions (compositor);
g_queue_init (transactions);
}