|
|
d1d875 |
From 8a951218911168ab386642769b98de42f177a279 Mon Sep 17 00:00:00 2001
|
|
|
d1d875 |
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
|
|
|
d1d875 |
Date: Fri, 17 Jun 2016 17:45:20 +0200
|
|
|
d1d875 |
Subject: [PATCH] surface-actor: Keep track of ignored damage
|
|
|
d1d875 |
|
|
|
d1d875 |
We ignore all damage while a surface is frozen and queue a full
|
|
|
d1d875 |
update instead once it's thawed. While not super efficient, this
|
|
|
d1d875 |
isn't overly bad for the intended case of catching up with any
|
|
|
d1d875 |
updates that happened during a compositor effect. However when
|
|
|
d1d875 |
extended frame sync is used, surfaces are also frozen while the
|
|
|
d1d875 |
client is drawing a frame, in which case the current behavior is
|
|
|
d1d875 |
pretty damaging (pun intended), as we end up redrawing the entire
|
|
|
d1d875 |
window each frame. To address this, keep track of the actual damage
|
|
|
d1d875 |
we ignore and apply it when the surface is thawed.
|
|
|
d1d875 |
|
|
|
d1d875 |
https://bugzilla.gnome.org/show_bug.cgi?id=767798
|
|
|
d1d875 |
---
|
|
|
d1d875 |
src/compositor/meta-surface-actor.c | 33 +++++++++++++++++++++------------
|
|
|
d1d875 |
1 file changed, 21 insertions(+), 12 deletions(-)
|
|
|
d1d875 |
|
|
|
d1d875 |
diff --git a/src/compositor/meta-surface-actor.c b/src/compositor/meta-surface-actor.c
|
|
|
d1d875 |
index bb85478..5844b37 100644
|
|
|
d1d875 |
--- a/src/compositor/meta-surface-actor.c
|
|
|
d1d875 |
+++ b/src/compositor/meta-surface-actor.c
|
|
|
d1d875 |
@@ -25,7 +25,7 @@ struct _MetaSurfaceActorPrivate
|
|
|
d1d875 |
cairo_region_t *input_region;
|
|
|
d1d875 |
|
|
|
d1d875 |
/* Freeze/thaw accounting */
|
|
|
d1d875 |
- guint needs_damage_all : 1;
|
|
|
d1d875 |
+ cairo_region_t *pending_damage;
|
|
|
d1d875 |
guint frozen : 1;
|
|
|
d1d875 |
};
|
|
|
d1d875 |
|
|
|
d1d875 |
@@ -247,9 +247,8 @@ meta_surface_actor_process_damage (MetaSurfaceActor *self,
|
|
|
d1d875 |
* here on the off chance that this will stop the corresponding
|
|
|
d1d875 |
* texture_from_pixmap from being update.
|
|
|
d1d875 |
*
|
|
|
d1d875 |
- * needs_damage_all tracks that some unknown damage happened while the
|
|
|
d1d875 |
- * window was frozen so that when the window becomes unfrozen we can
|
|
|
d1d875 |
- * issue a full window update to cover any lost damage.
|
|
|
d1d875 |
+ * pending_damage tracks any damage that happened while the window was
|
|
|
d1d875 |
+ * frozen so that when can apply it when the window becomes unfrozen.
|
|
|
d1d875 |
*
|
|
|
d1d875 |
* It should be noted that this is an unreliable mechanism since it's
|
|
|
d1d875 |
* quite likely that drivers will aim to provide a zero-copy
|
|
|
d1d875 |
@@ -257,7 +256,12 @@ meta_surface_actor_process_damage (MetaSurfaceActor *self,
|
|
|
d1d875 |
* any drawing done to the window is always immediately reflected in the
|
|
|
d1d875 |
* texture regardless of damage event handling.
|
|
|
d1d875 |
*/
|
|
|
d1d875 |
- priv->needs_damage_all = TRUE;
|
|
|
d1d875 |
+ cairo_rectangle_int_t rect = { .x = x, .y = y, .width = width, .height = height };
|
|
|
d1d875 |
+
|
|
|
d1d875 |
+ if (!priv->pending_damage)
|
|
|
d1d875 |
+ priv->pending_damage = cairo_region_create_rectangle (&rect);
|
|
|
d1d875 |
+ else
|
|
|
d1d875 |
+ cairo_region_union_rectangle (priv->pending_damage, &rect);
|
|
|
d1d875 |
return;
|
|
|
d1d875 |
}
|
|
|
d1d875 |
|
|
|
d1d875 |
@@ -318,16 +322,21 @@ meta_surface_actor_set_frozen (MetaSurfaceActor *self,
|
|
|
d1d875 |
|
|
|
d1d875 |
priv->frozen = frozen;
|
|
|
d1d875 |
|
|
|
d1d875 |
- if (!frozen && priv->needs_damage_all)
|
|
|
d1d875 |
+ if (!frozen && priv->pending_damage)
|
|
|
d1d875 |
{
|
|
|
d1d875 |
+ int i, n_rects = cairo_region_num_rectangles (priv->pending_damage);
|
|
|
d1d875 |
+ cairo_rectangle_int_t rect;
|
|
|
d1d875 |
+
|
|
|
d1d875 |
/* Since we ignore damage events while a window is frozen for certain effects
|
|
|
d1d875 |
- * we may need to issue an update_area() covering the whole pixmap if we
|
|
|
d1d875 |
- * don't know what real damage has happened. */
|
|
|
d1d875 |
+ * we need to apply the tracked damage now. */
|
|
|
d1d875 |
|
|
|
d1d875 |
- meta_surface_actor_process_damage (self, 0, 0,
|
|
|
d1d875 |
- clutter_actor_get_width (CLUTTER_ACTOR (priv->texture)),
|
|
|
d1d875 |
- clutter_actor_get_height (CLUTTER_ACTOR (priv->texture)));
|
|
|
d1d875 |
- priv->needs_damage_all = FALSE;
|
|
|
d1d875 |
+ for (i = 0; i < n_rects; i++)
|
|
|
d1d875 |
+ {
|
|
|
d1d875 |
+ cairo_region_get_rectangle (priv->pending_damage, i, &rect);
|
|
|
d1d875 |
+ meta_surface_actor_process_damage (self, rect.x, rect.y,
|
|
|
d1d875 |
+ rect.width, rect.height);
|
|
|
d1d875 |
+ }
|
|
|
d1d875 |
+ g_clear_pointer (&priv->pending_damage, cairo_region_destroy);
|
|
|
d1d875 |
}
|
|
|
d1d875 |
}
|
|
|
d1d875 |
|
|
|
d1d875 |
--
|
|
|
d1d875 |
2.7.4
|
|
|
d1d875 |
|