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>
This commit is contained in:
parent
17414fd242
commit
4048562961
@ -77,8 +77,7 @@
|
|||||||
|
|
||||||
typedef struct _QueueRedrawEntry
|
typedef struct _QueueRedrawEntry
|
||||||
{
|
{
|
||||||
gboolean has_clip;
|
GSList *clips;
|
||||||
ClutterPaintVolume clip;
|
|
||||||
} QueueRedrawEntry;
|
} QueueRedrawEntry;
|
||||||
|
|
||||||
typedef struct _PickRecord
|
typedef struct _PickRecord
|
||||||
@ -2542,11 +2541,13 @@ clutter_stage_queue_actor_redraw (ClutterStage *stage,
|
|||||||
|
|
||||||
entry = g_hash_table_lookup (priv->pending_queue_redraws, actor);
|
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
|
entry = g_new0 (QueueRedrawEntry, 1);
|
||||||
* (non-clipped) redraw of the actor has already been queued. */
|
g_hash_table_insert (priv->pending_queue_redraws,
|
||||||
if (!entry->has_clip)
|
g_object_ref (actor), entry);
|
||||||
|
}
|
||||||
|
else if (!entry->clips)
|
||||||
{
|
{
|
||||||
CLUTTER_NOTE (CLIPPING, "Bail from stage_queue_actor_redraw (%s): "
|
CLUTTER_NOTE (CLIPPING, "Bail from stage_queue_actor_redraw (%s): "
|
||||||
"Unclipped redraw of actor already queued",
|
"Unclipped redraw of actor already queued",
|
||||||
@ -2554,40 +2555,25 @@ clutter_stage_queue_actor_redraw (ClutterStage *stage,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If queuing a clipped redraw and a clipped redraw has
|
/* If queuing a clipped redraw then append the latest
|
||||||
* previously been queued for this actor then combine the latest
|
* clip to the clip list */
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
entry = g_new0 (QueueRedrawEntry, 1);
|
|
||||||
|
|
||||||
if (clip)
|
if (clip)
|
||||||
{
|
{
|
||||||
entry->has_clip = TRUE;
|
ClutterPaintVolume *clip_pv = _clutter_paint_volume_new (actor);
|
||||||
_clutter_paint_volume_init_static (&entry->clip, actor);
|
|
||||||
_clutter_paint_volume_set_from_volume (&entry->clip, clip);
|
_clutter_paint_volume_set_from_volume (clip_pv, clip);
|
||||||
|
entry->clips = g_slist_prepend (entry->clips, clip_pv);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
entry->has_clip = FALSE;
|
{
|
||||||
|
g_clear_slist (&entry->clips, (GDestroyNotify) clutter_paint_volume_free);
|
||||||
g_hash_table_insert (priv->pending_queue_redraws,
|
|
||||||
g_object_ref (actor), entry);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
free_queue_redraw_entry (QueueRedrawEntry *entry)
|
free_queue_redraw_entry (QueueRedrawEntry *entry)
|
||||||
{
|
{
|
||||||
if (entry->has_clip)
|
g_clear_slist (&entry->clips, (GDestroyNotify) clutter_paint_volume_free);
|
||||||
clutter_paint_volume_free (&entry->clip);
|
|
||||||
g_free (entry);
|
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 (&old_actor_pv, NULL);
|
||||||
_clutter_paint_volume_init_static (&new_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,
|
else if (clutter_actor_get_redraw_clip (redraw_actor,
|
||||||
&old_actor_pv,
|
&old_actor_pv,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user