mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 03:22:04 +00:00
surface-actor: Keep track of ignored damage
We ignore all damage while a surface is frozen and queue a full update instead once it's thawed. While not super efficient, this isn't overly bad for the intended case of catching up with any updates that happened during a compositor effect. However when extended frame sync is used, surfaces are also frozen while the client is drawing a frame, in which case the current behavior is pretty damaging (pun intended), as we end up redrawing the entire window each frame. To address this, keep track of the actual damage we ignore and apply it when the surface is thawed. https://bugzilla.gnome.org/show_bug.cgi?id=767798
This commit is contained in:
parent
989ec7fc60
commit
53a9411255
@ -25,7 +25,7 @@ struct _MetaSurfaceActorPrivate
|
||||
cairo_region_t *input_region;
|
||||
|
||||
/* Freeze/thaw accounting */
|
||||
guint needs_damage_all : 1;
|
||||
cairo_region_t *pending_damage;
|
||||
guint frozen : 1;
|
||||
};
|
||||
|
||||
@ -261,9 +261,8 @@ meta_surface_actor_process_damage (MetaSurfaceActor *self,
|
||||
* here on the off chance that this will stop the corresponding
|
||||
* texture_from_pixmap from being update.
|
||||
*
|
||||
* needs_damage_all tracks that some unknown damage happened while the
|
||||
* window was frozen so that when the window becomes unfrozen we can
|
||||
* issue a full window update to cover any lost damage.
|
||||
* pending_damage tracks any damage that happened while the window was
|
||||
* frozen so that when can apply it when the window becomes unfrozen.
|
||||
*
|
||||
* It should be noted that this is an unreliable mechanism since it's
|
||||
* quite likely that drivers will aim to provide a zero-copy
|
||||
@ -271,7 +270,12 @@ meta_surface_actor_process_damage (MetaSurfaceActor *self,
|
||||
* any drawing done to the window is always immediately reflected in the
|
||||
* texture regardless of damage event handling.
|
||||
*/
|
||||
priv->needs_damage_all = TRUE;
|
||||
cairo_rectangle_int_t rect = { .x = x, .y = y, .width = width, .height = height };
|
||||
|
||||
if (!priv->pending_damage)
|
||||
priv->pending_damage = cairo_region_create_rectangle (&rect);
|
||||
else
|
||||
cairo_region_union_rectangle (priv->pending_damage, &rect);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -332,16 +336,21 @@ meta_surface_actor_set_frozen (MetaSurfaceActor *self,
|
||||
|
||||
priv->frozen = frozen;
|
||||
|
||||
if (!frozen && priv->needs_damage_all)
|
||||
if (!frozen && priv->pending_damage)
|
||||
{
|
||||
/* Since we ignore damage events while a window is frozen for certain effects
|
||||
* we may need to issue an update_area() covering the whole pixmap if we
|
||||
* don't know what real damage has happened. */
|
||||
int i, n_rects = cairo_region_num_rectangles (priv->pending_damage);
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
meta_surface_actor_process_damage (self, 0, 0,
|
||||
clutter_actor_get_width (CLUTTER_ACTOR (priv->texture)),
|
||||
clutter_actor_get_height (CLUTTER_ACTOR (priv->texture)));
|
||||
priv->needs_damage_all = FALSE;
|
||||
/* Since we ignore damage events while a window is frozen for certain effects
|
||||
* we need to apply the tracked damage now. */
|
||||
|
||||
for (i = 0; i < n_rects; i++)
|
||||
{
|
||||
cairo_region_get_rectangle (priv->pending_damage, i, &rect);
|
||||
meta_surface_actor_process_damage (self, rect.x, rect.y,
|
||||
rect.width, rect.height);
|
||||
}
|
||||
g_clear_pointer (&priv->pending_damage, cairo_region_destroy);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user