wayland/surface: Use transactions for applying committed states

A transaction contains the committed state for a surface, plus any
cached state for synchronized subsurfaces.

v2:
* Handle sub-surface positions separately from surface states.
v3:
* Sync child states only for surfaces with state in the transaction.
v4: (Jonas Ådahl)
* Drop unnecessary g_object_new call from wl_subsurface_set_desync. (me)
* Fix indentation & formatting in meta_wayland_surface_commit.
* Add meta_wayland_surface_state_new helper function.
* Fix alignment of meta_wayland_transaction_apply_subsurface_position
  parameters.
* Add curly braces around meta_wayland_transaction_sync_child_states
  call in meta_wayland_transaction_apply.
v5:
* Make meta_wayland_surface_state_new an inline function.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1880>
This commit is contained in:
Michel Dänzer 2021-05-28 12:39:48 +02:00 committed by Michel Dänzer
parent 56260e3e07
commit 0bae4ece19
6 changed files with 125 additions and 60 deletions

View File

@ -28,6 +28,7 @@
#include "wayland/meta-wayland-actor-surface.h"
#include "wayland/meta-wayland-buffer.h"
#include "wayland/meta-wayland-surface.h"
#include "wayland/meta-wayland-transaction.h"
#include "wayland/meta-window-wayland.h"
struct _MetaWaylandSubsurface
@ -105,28 +106,6 @@ is_sibling (MetaWaylandSurface *surface,
return surface != sibling && surface->sub.parent == sibling->sub.parent;
}
void
meta_wayland_subsurface_parent_state_applied (MetaWaylandSubsurface *subsurface)
{
MetaWaylandSurfaceRole *surface_role = META_WAYLAND_SURFACE_ROLE (subsurface);
MetaWaylandActorSurface *actor_surface =
META_WAYLAND_ACTOR_SURFACE (subsurface);
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
if (surface->sub.pending_pos)
{
surface->sub.x = surface->sub.pending_x;
surface->sub.y = surface->sub.pending_y;
surface->sub.pending_pos = FALSE;
}
if (meta_wayland_surface_is_synchronized (surface))
meta_wayland_surface_apply_cached_state (surface);
meta_wayland_actor_surface_sync_actor_state (actor_surface);
}
void
meta_wayland_subsurface_union_geometry (MetaWaylandSubsurface *subsurface,
int parent_x,
@ -452,7 +431,13 @@ wl_subsurface_set_desync (struct wl_client *client,
meta_wayland_surface_is_synchronized (surface->sub.parent);
if (!is_parent_effectively_synchronized)
meta_wayland_surface_apply_cached_state (surface);
{
MetaWaylandTransaction *transaction;
transaction = meta_wayland_transaction_new (surface->compositor);
meta_wayland_transaction_add_cached_states (transaction, surface);
meta_wayland_transaction_commit (transaction);
}
surface->sub.synchronous = FALSE;
}

View File

@ -44,8 +44,6 @@ typedef struct
struct wl_listener sibling_destroy_listener;
} MetaWaylandSubsurfacePlacementOp;
void meta_wayland_subsurface_parent_state_applied (MetaWaylandSubsurface *subsurface);
void meta_wayland_subsurface_union_geometry (MetaWaylandSubsurface *subsurface,
int parent_x,
int parent_y,

View File

@ -48,6 +48,7 @@
#include "wayland/meta-wayland-region.h"
#include "wayland/meta-wayland-seat.h"
#include "wayland/meta-wayland-subsurface.h"
#include "wayland/meta-wayland-transaction.h"
#include "wayland/meta-wayland-viewporter.h"
#include "wayland/meta-wayland-xdg-shell.h"
#include "wayland/meta-window-wayland.h"
@ -717,7 +718,6 @@ void
meta_wayland_surface_apply_state (MetaWaylandSurface *surface,
MetaWaylandSurfaceState *state)
{
MetaWaylandSurface *subsurface_surface;
gboolean had_damage = FALSE;
int old_width, old_height;
@ -956,14 +956,6 @@ cleanup:
surface_state_signals[SURFACE_STATE_SIGNAL_APPLIED],
0);
META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface)
{
MetaWaylandSubsurface *subsurface;
subsurface = META_WAYLAND_SUBSURFACE (subsurface_surface->role);
meta_wayland_subsurface_parent_state_applied (subsurface);
}
if (had_damage)
{
MetaWindow *toplevel_window;
@ -984,22 +976,6 @@ cleanup:
meta_wayland_surface_role_post_apply_state (surface->role, state);
}
static void
ensure_cached_state (MetaWaylandSurface *surface)
{
if (!surface->cached_state)
surface->cached_state = g_object_new (META_TYPE_WAYLAND_SURFACE_STATE,
NULL);
}
void
meta_wayland_surface_apply_cached_state (MetaWaylandSurface *surface)
{
ensure_cached_state (surface);
meta_wayland_surface_apply_state (surface, surface->cached_state);
meta_wayland_surface_state_reset (surface->cached_state);
}
MetaWaylandSurfaceState *
meta_wayland_surface_get_pending_state (MetaWaylandSurface *surface)
{
@ -1028,16 +1004,30 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface)
*/
if (meta_wayland_surface_is_synchronized (surface))
{
ensure_cached_state (surface);
meta_wayland_surface_state_merge_into (pending, surface->cached_state);
if (surface->cached_state)
{
meta_wayland_surface_state_merge_into (pending, surface->cached_state);
meta_wayland_surface_state_reset (pending);
}
else
{
surface->cached_state = pending;
surface->pending_state = meta_wayland_surface_state_new ();
}
}
else
{
meta_wayland_surface_apply_state (surface, surface->pending_state);
}
MetaWaylandTransaction *transaction;
meta_wayland_surface_state_reset (pending);
transaction = meta_wayland_transaction_new (surface->compositor);
meta_wayland_transaction_add_state (transaction, surface, pending);
if (surface->sub.pending_pos)
meta_wayland_transaction_add_subsurface_position (transaction, surface);
meta_wayland_transaction_add_cached_child_states (transaction, surface);
meta_wayland_transaction_commit (transaction);
surface->pending_state = meta_wayland_surface_state_new ();
}
}
static void
@ -1745,7 +1735,7 @@ meta_wayland_surface_get_absolute_coordinates (MetaWaylandSurface *surface,
static void
meta_wayland_surface_init (MetaWaylandSurface *surface)
{
surface->pending_state = g_object_new (META_TYPE_WAYLAND_SURFACE_STATE, NULL);
surface->pending_state = meta_wayland_surface_state_new ();
surface->buffer_ref = meta_wayland_buffer_ref_new ();

View File

@ -276,7 +276,8 @@ void meta_wayland_surface_apply_state (MetaWaylandSurface *s
MetaWaylandSurfaceState *
meta_wayland_surface_get_pending_state (MetaWaylandSurface *surface);
void meta_wayland_surface_apply_cached_state (MetaWaylandSurface *surface);
MetaWaylandSurfaceState *
meta_wayland_surface_ensure_cached_state (MetaWaylandSurface *surface);
gboolean meta_wayland_surface_assign_role (MetaWaylandSurface *surface,
GType role_type,
@ -386,6 +387,12 @@ meta_wayland_surface_can_scanout_untransformed (MetaWaylandSurface *surface,
int meta_wayland_surface_get_geometry_scale (MetaWaylandSurface *surface);
static inline MetaWaylandSurfaceState *
meta_wayland_surface_state_new (void)
{
return g_object_new (META_TYPE_WAYLAND_SURFACE_STATE, NULL);
}
static inline GNode *
meta_get_next_subsurface_sibling (GNode *n)
{

View File

@ -41,6 +41,11 @@ struct _MetaWaylandTransaction
typedef struct _MetaWaylandTransactionEntry
{
MetaWaylandSurfaceState *state;
/* Sub-surface position */
gboolean has_sub_pos;
int x;
int y;
} MetaWaylandTransactionEntry;
static MetaWaylandTransactionEntry *
@ -66,6 +71,17 @@ meta_wayland_transaction_sync_child_states (MetaWaylandSurface *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;
}
static gboolean
is_ancestor (MetaWaylandSurface *candidate,
MetaWaylandSurface *reference)
@ -149,11 +165,13 @@ meta_wayland_transaction_apply (MetaWaylandTransaction *transaction,
MetaWaylandTransaction **first_candidate)
{
g_autofree MetaWaylandSurface **surfaces = NULL;
g_autofree MetaWaylandSurfaceState **states = NULL;
unsigned int num_surfaces;
int i;
surfaces = (MetaWaylandSurface **)
g_hash_table_get_keys_as_array (transaction->entries, &num_surfaces);
states = g_new (MetaWaylandSurfaceState *, num_surfaces);
/* Sort surfaces from ancestors to descendants */
qsort (surfaces, num_surfaces, sizeof (MetaWaylandSurface *),
@ -166,7 +184,10 @@ meta_wayland_transaction_apply (MetaWaylandTransaction *transaction,
MetaWaylandTransactionEntry *entry;
entry = meta_wayland_transaction_get_entry (transaction, surface);
meta_wayland_surface_apply_state (surface, entry->state);
states[i] = entry->state;
meta_wayland_transaction_apply_subsurface_position (surface, entry);
if (entry->state)
meta_wayland_surface_apply_state (surface, entry->state);
if (surface->transaction.last_committed == transaction)
{
@ -188,7 +209,10 @@ meta_wayland_transaction_apply (MetaWaylandTransaction *transaction,
/* Synchronize child states from descendants to ancestors */
for (i = num_surfaces - 1; i >= 0; i--)
meta_wayland_transaction_sync_child_states (surfaces[i]);
{
if (states[i])
meta_wayland_transaction_sync_child_states (surfaces[i]);
}
meta_wayland_transaction_free (transaction);
}
@ -296,6 +320,58 @@ meta_wayland_transaction_add_state (MetaWaylandTransaction *transaction,
entry->state = state;
}
void
meta_wayland_transaction_add_subsurface_position (MetaWaylandTransaction *transaction,
MetaWaylandSurface *surface)
{
MetaWaylandTransactionEntry *entry;
entry = meta_wayland_transaction_ensure_entry (transaction, surface);
entry->x = surface->sub.pending_x;
entry->y = surface->sub.pending_y;
entry->has_sub_pos = TRUE;
surface->sub.pending_pos = FALSE;
}
static gboolean
meta_wayland_transaction_add_cached_state (MetaWaylandTransaction *transaction,
MetaWaylandSurface *surface)
{
MetaWaylandSurfaceState *cached = surface->cached_state;
gboolean is_synchronized;
is_synchronized = meta_wayland_surface_is_synchronized (surface);
if (is_synchronized && cached)
{
meta_wayland_transaction_add_state (transaction, surface, cached);
surface->cached_state = NULL;
}
if (surface->sub.pending_pos)
meta_wayland_transaction_add_subsurface_position (transaction, surface);
return is_synchronized;
}
void
meta_wayland_transaction_add_cached_child_states (MetaWaylandTransaction *transaction,
MetaWaylandSurface *surface)
{
MetaWaylandSurface *subsurface_surface;
META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface)
meta_wayland_transaction_add_cached_states (transaction, subsurface_surface);
}
void
meta_wayland_transaction_add_cached_states (MetaWaylandTransaction *transaction,
MetaWaylandSurface *surface)
{
if (meta_wayland_transaction_add_cached_state (transaction, surface))
meta_wayland_transaction_add_cached_child_states (transaction, surface);
}
static void
meta_wayland_transaction_entry_free (MetaWaylandTransactionEntry *entry)
{

View File

@ -28,6 +28,15 @@ void meta_wayland_transaction_add_state (MetaWaylandTransaction *transaction,
MetaWaylandSurface *surface,
MetaWaylandSurfaceState *state);
void meta_wayland_transaction_add_subsurface_position (MetaWaylandTransaction *transaction,
MetaWaylandSurface *surface);
void meta_wayland_transaction_add_cached_states (MetaWaylandTransaction *transaction,
MetaWaylandSurface *surface);
void meta_wayland_transaction_add_cached_child_states (MetaWaylandTransaction *transaction,
MetaWaylandSurface *surface);
MetaWaylandTransaction *meta_wayland_transaction_new (MetaWaylandCompositor *compositor);
void meta_wayland_transaction_free (MetaWaylandTransaction *transaction);