summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2014-10-09 10:09:51 +0200
committerAlexander Larsson <alexl@redhat.com>2014-10-09 10:09:51 +0200
commit91f99ed80785517169d46a2ff9e1b0e74c2c6d35 (patch)
treefc16030e7feaaf3b16b63210f74fd876c62d536f
parent76ab606cef221478289cbf00227e16dedf2dcb17 (diff)
downloadgtk+-91f99ed80785517169d46a2ff9e1b0e74c2c6d35.tar.gz
Change the way the update area is tracked during paint
First of all we track the current update area during an update in window->active_update_area. This will be used later in end_paint to know the damaged area. Secondly we keep track of old update areas for the last 2 frames. This will later allow us to reuse old framebuffer contents in double or tripple buffer setups, only painting what has changed since then.
-rw-r--r--gdk/gdkinternals.h6
-rw-r--r--gdk/gdkwindow.c47
2 files changed, 46 insertions, 7 deletions
diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h
index 07df2f15de..d70b6c4742 100644
--- a/gdk/gdkinternals.h
+++ b/gdk/gdkinternals.h
@@ -213,6 +213,12 @@ struct _GdkWindow
cairo_region_t *update_area;
guint update_freeze_count;
+ /* This is the update_area that was in effect when the current expose
+ started. It may be smaller than the expose area if we'e painting
+ more than we have to, but it represents the "true" damage. */
+ cairo_region_t *active_update_area;
+ /* We store the old expose areas to support buffer-age optimizations */
+ cairo_region_t *old_updated_area[2];
GdkWindowState state;
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index f5eb162942..2e349ca661 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -1024,9 +1024,35 @@ recompute_visible_regions (GdkWindow *private,
recalculate_children);
}
+static void
+gdk_window_clear_old_updated_area (GdkWindow *window)
+{
+ int i;
+
+ for (i = 0; i < 2; i++)
+ {
+ if (window->old_updated_area[i])
+ {
+ cairo_region_destroy (window->old_updated_area[i]);
+ window->old_updated_area[i] = NULL;
+ }
+ }
+}
+
+static void
+gdk_window_append_old_updated_area (GdkWindow *window,
+ cairo_region_t *region)
+{
+ if (window->old_updated_area[1])
+ cairo_region_destroy (window->old_updated_area[1]);
+ window->old_updated_area[1] = window->old_updated_area[0];
+ window->old_updated_area[0] = cairo_region_reference (region);
+}
+
void
_gdk_window_update_size (GdkWindow *window)
{
+ gdk_window_clear_old_updated_area (window);
recompute_visible_regions (window, FALSE);
}
@@ -3375,15 +3401,19 @@ gdk_window_process_updates_internal (GdkWindow *window)
*/
if (window->update_area)
{
- cairo_region_t *update_area = window->update_area;
+ g_assert (window->active_update_area == NULL); /* No reentrancy */
+
+ window->active_update_area = window->update_area;
window->update_area = NULL;
if (gdk_window_is_viewable (window))
{
cairo_region_t *expose_region;
+ expose_region = cairo_region_copy (window->active_update_area);
+
/* Clip to part visible in impl window */
- cairo_region_intersect (update_area, window->clip_region);
+ cairo_region_intersect (expose_region, window->clip_region);
if (debug_updates)
{
@@ -3395,14 +3425,15 @@ gdk_window_process_updates_internal (GdkWindow *window)
impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
if (impl_class->queue_antiexpose)
- impl_class->queue_antiexpose (window, update_area);
+ impl_class->queue_antiexpose (window, expose_region);
- expose_region = cairo_region_copy (update_area);
impl_class->process_updates_recurse (window, expose_region);
- cairo_region_destroy (expose_region);
- }
- cairo_region_destroy (update_area);
+ gdk_window_append_old_updated_area (window, window->active_update_area);
+ }
+
+ cairo_region_destroy (window->active_update_area);
+ window->active_update_area = NULL;
}
window->in_update = FALSE;
@@ -5046,6 +5077,7 @@ gdk_window_hide (GdkWindow *window)
impl_class->hide (window);
}
+ gdk_window_clear_old_updated_area (window);
recompute_visible_regions (window, FALSE);
/* all decendants became non-visible, we need to send visibility notify */
@@ -5105,6 +5137,7 @@ gdk_window_withdraw (GdkWindow *window)
}
recompute_visible_regions (window, FALSE);
+ gdk_window_clear_old_updated_area (window);
}
}