diff options
author | msizanoen1 <msizanoen@qtmlabs.xyz> | 2023-04-17 17:51:58 +0700 |
---|---|---|
committer | Marge Bot <marge-bot@gnome.org> | 2023-05-03 08:53:36 +0000 |
commit | 4048562961c461c33ab7dfcb1bdd9066004a9a11 (patch) | |
tree | afdc241d8a2fcbd21bfeee1c721f9fa620b644c7 | |
parent | 17414fd242009f12b769f637b84c1615195990ef (diff) | |
download | mutter-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.c | 67 |
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, |