summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichel Dänzer <mdaenzer@redhat.com>2021-05-28 12:39:48 +0200
committerMichel Dänzer <michel@daenzer.net>2022-12-01 12:41:32 +0100
commit0bae4ece19c5c9616491d94c84aa58eb718b039f (patch)
treea88b3043597cd26234fd15cf9af76c49c4f8f185
parent56260e3e0726c970c572a339e18b1f6ebed3069c (diff)
downloadmutter-0bae4ece19c5c9616491d94c84aa58eb718b039f.tar.gz
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>
-rw-r--r--src/wayland/meta-wayland-subsurface.c31
-rw-r--r--src/wayland/meta-wayland-subsurface.h2
-rw-r--r--src/wayland/meta-wayland-surface.c54
-rw-r--r--src/wayland/meta-wayland-surface.h9
-rw-r--r--src/wayland/meta-wayland-transaction.c80
-rw-r--r--src/wayland/meta-wayland-transaction.h9
6 files changed, 125 insertions, 60 deletions
diff --git a/src/wayland/meta-wayland-subsurface.c b/src/wayland/meta-wayland-subsurface.c
index 6a50b3299..ba86d6206 100644
--- a/src/wayland/meta-wayland-subsurface.c
+++ b/src/wayland/meta-wayland-subsurface.c
@@ -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
@@ -106,28 +107,6 @@ is_sibling (MetaWaylandSurface *surface,
}
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,
int parent_y,
@@ -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;
}
diff --git a/src/wayland/meta-wayland-subsurface.h b/src/wayland/meta-wayland-subsurface.h
index 45dbf8626..5fa2999db 100644
--- a/src/wayland/meta-wayland-subsurface.h
+++ b/src/wayland/meta-wayland-subsurface.h
@@ -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,
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index adc8ba836..852bbed99 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -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 ();
diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h
index 56bcbb189..ddd86ec1a 100644
--- a/src/wayland/meta-wayland-surface.h
+++ b/src/wayland/meta-wayland-surface.h
@@ -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)
{
diff --git a/src/wayland/meta-wayland-transaction.c b/src/wayland/meta-wayland-transaction.c
index 96a0b18bc..bfcf42580 100644
--- a/src/wayland/meta-wayland-transaction.c
+++ b/src/wayland/meta-wayland-transaction.c
@@ -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)
{
diff --git a/src/wayland/meta-wayland-transaction.h b/src/wayland/meta-wayland-transaction.h
index 230548c19..d79f8d94c 100644
--- a/src/wayland/meta-wayland-transaction.h
+++ b/src/wayland/meta-wayland-transaction.h
@@ -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);