summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormsizanoen1 <msizanoen@qtmlabs.xyz>2023-04-17 17:51:58 +0700
committerMarge Bot <marge-bot@gnome.org>2023-05-03 08:53:36 +0000
commit4048562961c461c33ab7dfcb1bdd9066004a9a11 (patch)
treeafdc241d8a2fcbd21bfeee1c721f9fa620b644c7
parent17414fd242009f12b769f637b84c1615195990ef (diff)
downloadmutter-4048562961c461c33ab7dfcb1bdd9066004a9a11.tar.gz
stage: Keep queued actor redraw clip volumes separate
This aims to reduce the amount of pixels that have to be redrawed on the screen on a clipped actor redraw in case using the union of two different clips in a surface will substantially increase the redrawn area. This should not result in excessive memory consumption as callers of `clutter_actor_queue_redraw_with_clip` are expected to ensure that the redraw clip rectangles are adequately deduplicated. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2965>
-rw-r--r--clutter/clutter/clutter-stage.c67
1 files changed, 28 insertions, 39 deletions
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
index 14774f6f0..4afb5b705 100644
--- a/clutter/clutter/clutter-stage.c
+++ b/clutter/clutter/clutter-stage.c
@@ -77,8 +77,7 @@
typedef struct _QueueRedrawEntry
{
- gboolean has_clip;
- ClutterPaintVolume clip;
+ GSList *clips;
} QueueRedrawEntry;
typedef struct _PickRecord
@@ -2542,52 +2541,39 @@ clutter_stage_queue_actor_redraw (ClutterStage *stage,
entry = g_hash_table_lookup (priv->pending_queue_redraws, actor);
- if (entry)
+ if (!entry)
{
- /* Ignore all requests to queue a redraw for an actor if a full
- * (non-clipped) redraw of the actor has already been queued. */
- if (!entry->has_clip)
- {
- CLUTTER_NOTE (CLIPPING, "Bail from stage_queue_actor_redraw (%s): "
- "Unclipped redraw of actor already queued",
- _clutter_actor_get_debug_name (actor));
- return;
- }
-
- /* If queuing a clipped redraw and a clipped redraw has
- * previously been queued for this actor then combine the latest
- * clip together with the existing clip */
- if (clip)
- clutter_paint_volume_union (&entry->clip, clip);
- else
- {
- clutter_paint_volume_free (&entry->clip);
- entry->has_clip = FALSE;
- }
+ entry = g_new0 (QueueRedrawEntry, 1);
+ g_hash_table_insert (priv->pending_queue_redraws,
+ g_object_ref (actor), entry);
}
- else
+ else if (!entry->clips)
{
- entry = g_new0 (QueueRedrawEntry, 1);
+ CLUTTER_NOTE (CLIPPING, "Bail from stage_queue_actor_redraw (%s): "
+ "Unclipped redraw of actor already queued",
+ _clutter_actor_get_debug_name (actor));
+ return;
+ }
- if (clip)
- {
- entry->has_clip = TRUE;
- _clutter_paint_volume_init_static (&entry->clip, actor);
- _clutter_paint_volume_set_from_volume (&entry->clip, clip);
- }
- else
- entry->has_clip = FALSE;
+ /* If queuing a clipped redraw then append the latest
+ * clip to the clip list */
+ if (clip)
+ {
+ ClutterPaintVolume *clip_pv = _clutter_paint_volume_new (actor);
- g_hash_table_insert (priv->pending_queue_redraws,
- g_object_ref (actor), entry);
+ _clutter_paint_volume_set_from_volume (clip_pv, clip);
+ entry->clips = g_slist_prepend (entry->clips, clip_pv);
+ }
+ else
+ {
+ g_clear_slist (&entry->clips, (GDestroyNotify) clutter_paint_volume_free);
}
}
static void
free_queue_redraw_entry (QueueRedrawEntry *entry)
{
- if (entry->has_clip)
- clutter_paint_volume_free (&entry->clip);
+ g_clear_slist (&entry->clips, (GDestroyNotify) clutter_paint_volume_free);
g_free (entry);
}
@@ -2682,9 +2668,12 @@ clutter_stage_maybe_finish_queue_redraws (ClutterStage *stage)
_clutter_paint_volume_init_static (&old_actor_pv, NULL);
_clutter_paint_volume_init_static (&new_actor_pv, NULL);
- if (entry->has_clip)
+ if (entry->clips)
{
- add_to_stage_clip (stage, &entry->clip);
+ GSList *l;
+
+ for (l = entry->clips; l; l = l->next)
+ add_to_stage_clip (stage, l->data);
}
else if (clutter_actor_get_redraw_clip (redraw_actor,
&old_actor_pv,