forked from AuroraMiddleware/gtk
gdk: Don't ever do copies from the window
This basically neuters gdk_window_move_region, gdk_window_scroll and gdk_window_move_resize, in that they now never copy any bits but just invalidate the source and destination regions. This is a performance loss, but the hope is that the simplifications it later allows will let us recover this performance loss (which mainly affects scrolling).
This commit is contained in:
parent
e9122eca68
commit
6a478ea672
285
gdk/gdkwindow.c
285
gdk/gdkwindow.c
@ -6120,64 +6120,6 @@ move_native_children (GdkWindow *private)
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
collect_native_child_region_helper (GdkWindow *window,
|
||||
GdkWindowImpl *impl,
|
||||
cairo_region_t **region,
|
||||
int x_offset,
|
||||
int y_offset)
|
||||
{
|
||||
GdkWindow *child;
|
||||
cairo_region_t *tmp;
|
||||
GList *l;
|
||||
|
||||
for (l = window->children; l != NULL; l = l->next)
|
||||
{
|
||||
child = l->data;
|
||||
|
||||
if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only)
|
||||
continue;
|
||||
|
||||
if (child->impl != impl)
|
||||
{
|
||||
tmp = cairo_region_copy (child->clip_region);
|
||||
cairo_region_translate (tmp,
|
||||
x_offset + child->x,
|
||||
y_offset + child->y);
|
||||
if (*region == NULL)
|
||||
*region = tmp;
|
||||
else
|
||||
{
|
||||
cairo_region_union (*region, tmp);
|
||||
cairo_region_destroy (tmp);
|
||||
}
|
||||
}
|
||||
else
|
||||
collect_native_child_region_helper (child, impl, region,
|
||||
x_offset + child->x,
|
||||
y_offset + child->y);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static cairo_region_t *
|
||||
collect_native_child_region (GdkWindow *window,
|
||||
gboolean include_this)
|
||||
{
|
||||
cairo_region_t *region;
|
||||
|
||||
if (include_this && gdk_window_has_impl (window) && window->viewable)
|
||||
return cairo_region_copy (window->clip_region);
|
||||
|
||||
region = NULL;
|
||||
|
||||
collect_native_child_region_helper (window, window->impl, ®ion, 0, 0);
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gdk_window_move_resize_internal (GdkWindow *window,
|
||||
gboolean with_move,
|
||||
@ -6186,13 +6128,10 @@ gdk_window_move_resize_internal (GdkWindow *window,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
cairo_region_t *old_region, *old_layered, *new_region, *copy_area;
|
||||
cairo_region_t *old_native_child_region, *new_native_child_region;
|
||||
GdkWindow *impl_window;
|
||||
cairo_region_t *old_region, *new_region;
|
||||
GdkWindowImplClass *impl_class;
|
||||
gboolean expose;
|
||||
int old_x, old_y, old_abs_x, old_abs_y;
|
||||
int dx, dy;
|
||||
int old_abs_x, old_abs_y;
|
||||
|
||||
g_return_if_fail (GDK_IS_WINDOW (window));
|
||||
|
||||
@ -6217,39 +6156,15 @@ gdk_window_move_resize_internal (GdkWindow *window,
|
||||
|
||||
expose = FALSE;
|
||||
old_region = NULL;
|
||||
old_layered = NULL;
|
||||
|
||||
impl_window = gdk_window_get_impl_window (window);
|
||||
|
||||
old_x = window->x;
|
||||
old_y = window->y;
|
||||
|
||||
old_native_child_region = NULL;
|
||||
if (gdk_window_is_viewable (window) &&
|
||||
!window->input_only)
|
||||
{
|
||||
expose = TRUE;
|
||||
|
||||
old_region = cairo_region_copy (window->clip_region);
|
||||
old_layered = cairo_region_copy (window->layered_region);
|
||||
/* Adjust regions to parent window coords */
|
||||
cairo_region_translate (old_region, window->x, window->y);
|
||||
cairo_region_translate (old_layered, window->x, window->y);
|
||||
|
||||
old_native_child_region = collect_native_child_region (window, TRUE);
|
||||
if (old_native_child_region)
|
||||
{
|
||||
/* Adjust region to parent window coords */
|
||||
cairo_region_translate (old_native_child_region, window->x, window->y);
|
||||
|
||||
/* Any native window move will immediately copy stuff to the destination, which may overwrite a
|
||||
* source or destination for a delayed GdkWindowRegionMove. So, we need
|
||||
* to flush those here for the parent window and all overlapped subwindows
|
||||
* of it. And we need to do this before setting the new clips as those will be
|
||||
* affecting this.
|
||||
*/
|
||||
gdk_window_flush_recursive (window->parent);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the new position and size */
|
||||
@ -6268,22 +6183,11 @@ gdk_window_move_resize_internal (GdkWindow *window,
|
||||
window->height = height;
|
||||
}
|
||||
|
||||
dx = window->x - old_x;
|
||||
dy = window->y - old_y;
|
||||
|
||||
old_abs_x = window->abs_x;
|
||||
old_abs_y = window->abs_y;
|
||||
|
||||
recompute_visible_regions (window, TRUE, FALSE);
|
||||
|
||||
new_native_child_region = NULL;
|
||||
if (old_native_child_region)
|
||||
{
|
||||
new_native_child_region = collect_native_child_region (window, TRUE);
|
||||
/* Adjust region to parent window coords */
|
||||
cairo_region_translate (new_native_child_region, window->x, window->y);
|
||||
}
|
||||
|
||||
if (gdk_window_has_impl (window))
|
||||
{
|
||||
impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
|
||||
@ -6304,87 +6208,14 @@ gdk_window_move_resize_internal (GdkWindow *window,
|
||||
/* Adjust region to parent window coords */
|
||||
cairo_region_translate (new_region, window->x, window->y);
|
||||
|
||||
/* copy_area:
|
||||
* Part of the data at the new location can be copied from the
|
||||
* old location, this area is the intersection of the old region
|
||||
* moved as the copy will move it and then intersected with
|
||||
* the new region.
|
||||
*
|
||||
* new_region:
|
||||
* Everything in the old and new regions that is not copied must be
|
||||
* invalidated (including children) as this is newly exposed
|
||||
*/
|
||||
if (gdk_window_has_alpha (window))
|
||||
copy_area = cairo_region_create (); /* Copy nothing for alpha windows */
|
||||
else
|
||||
copy_area = cairo_region_copy (new_region);
|
||||
|
||||
/* Don't copy from a previously layered region */
|
||||
cairo_region_translate (old_layered, dx, dy);
|
||||
cairo_region_subtract (copy_area, old_layered);
|
||||
|
||||
/* Don't copy into a layered region */
|
||||
cairo_region_translate (copy_area, -window->x, -window->y);
|
||||
cairo_region_subtract (copy_area, window->layered_region);
|
||||
cairo_region_translate (copy_area, window->x, window->y);
|
||||
|
||||
cairo_region_union (new_region, old_region);
|
||||
|
||||
if (old_native_child_region)
|
||||
{
|
||||
/* Don't copy from inside native children, as this is copied by
|
||||
* the native window move.
|
||||
*/
|
||||
cairo_region_subtract (old_region, old_native_child_region);
|
||||
}
|
||||
cairo_region_translate (old_region, dx, dy);
|
||||
|
||||
cairo_region_intersect (copy_area, old_region);
|
||||
|
||||
if (new_native_child_region)
|
||||
{
|
||||
/* Don't copy any bits that would cause a read from the moved
|
||||
native windows, as we can't read that data */
|
||||
cairo_region_translate (new_native_child_region, dx, dy);
|
||||
cairo_region_subtract (copy_area, new_native_child_region);
|
||||
cairo_region_translate (new_native_child_region, -dx, -dy);
|
||||
}
|
||||
|
||||
cairo_region_subtract (new_region, copy_area);
|
||||
|
||||
/* Convert old region to impl coords */
|
||||
cairo_region_translate (old_region, -dx + window->abs_x - window->x, -dy + window->abs_y - window->y);
|
||||
|
||||
/* convert from parent coords to impl */
|
||||
cairo_region_translate (copy_area, window->abs_x - window->x, window->abs_y - window->y);
|
||||
|
||||
move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
|
||||
|
||||
/* Invalidate affected part in the parent window
|
||||
* (no higher window should be affected)
|
||||
* We also invalidate any children in that area, which could include
|
||||
* this window if it still overlaps that area.
|
||||
*/
|
||||
if (old_native_child_region)
|
||||
{
|
||||
/* No need to expose the region that the native window move copies */
|
||||
cairo_region_translate (old_native_child_region, dx, dy);
|
||||
cairo_region_intersect (old_native_child_region, new_native_child_region);
|
||||
cairo_region_subtract (new_region, old_native_child_region);
|
||||
}
|
||||
gdk_window_invalidate_region_full (window->parent, new_region, TRUE, CLEAR_BG_ALL);
|
||||
|
||||
cairo_region_destroy (old_region);
|
||||
cairo_region_destroy (old_layered);
|
||||
cairo_region_destroy (new_region);
|
||||
}
|
||||
|
||||
if (old_native_child_region)
|
||||
{
|
||||
cairo_region_destroy (old_native_child_region);
|
||||
cairo_region_destroy (new_native_child_region);
|
||||
}
|
||||
|
||||
_gdk_synthesize_crossing_events_for_geometry_change (window);
|
||||
}
|
||||
|
||||
@ -6484,9 +6315,6 @@ gdk_window_scroll (GdkWindow *window,
|
||||
gint dx,
|
||||
gint dy)
|
||||
{
|
||||
GdkWindow *impl_window;
|
||||
cairo_region_t *copy_area, *noncopy_area, *old_layered_area;
|
||||
cairo_region_t *old_native_child_region, *new_native_child_region;
|
||||
GList *tmp_list;
|
||||
|
||||
g_return_if_fail (GDK_IS_WINDOW (window));
|
||||
@ -6497,20 +6325,6 @@ gdk_window_scroll (GdkWindow *window,
|
||||
if (window->destroyed)
|
||||
return;
|
||||
|
||||
old_layered_area = cairo_region_copy (window->layered_region);
|
||||
old_native_child_region = collect_native_child_region (window, FALSE);
|
||||
if (old_native_child_region)
|
||||
{
|
||||
/* Any native window move will immediately copy stuff to the destination, which may overwrite a
|
||||
* source or destination for a delayed GdkWindowRegionMove. So, we need
|
||||
* to flush those here for the window and all overlapped subwindows
|
||||
* of it. And we need to do this before setting the new clips as those will be
|
||||
* affecting this.
|
||||
*/
|
||||
gdk_window_flush_recursive (window);
|
||||
}
|
||||
|
||||
|
||||
/* First move all child windows, without causing invalidation */
|
||||
|
||||
tmp_list = window->children;
|
||||
@ -6527,64 +6341,9 @@ gdk_window_scroll (GdkWindow *window,
|
||||
|
||||
recompute_visible_regions (window, FALSE, TRUE);
|
||||
|
||||
new_native_child_region = NULL;
|
||||
if (old_native_child_region)
|
||||
new_native_child_region = collect_native_child_region (window, FALSE);
|
||||
|
||||
move_native_children (window);
|
||||
|
||||
/* Then copy the actual bits of the window w/ child windows */
|
||||
|
||||
impl_window = gdk_window_get_impl_window (window);
|
||||
|
||||
/* Calculate the area that can be gotten by copying the old area */
|
||||
if (gdk_window_has_alpha (window))
|
||||
copy_area = cairo_region_create (); /* Copy nothing for alpha windows */
|
||||
else
|
||||
copy_area = cairo_region_copy (window->clip_region);
|
||||
cairo_region_subtract (copy_area, old_layered_area);
|
||||
if (old_native_child_region)
|
||||
{
|
||||
/* Don't copy from inside native children, as this is copied by
|
||||
* the native window move.
|
||||
*/
|
||||
cairo_region_subtract (copy_area, old_native_child_region);
|
||||
|
||||
/* Don't copy any bits that would cause a read from the moved
|
||||
native windows, as we can't read that data */
|
||||
cairo_region_subtract (copy_area, new_native_child_region);
|
||||
}
|
||||
cairo_region_translate (copy_area, dx, dy);
|
||||
cairo_region_intersect (copy_area, window->clip_region);
|
||||
cairo_region_subtract (copy_area, window->layered_region);
|
||||
|
||||
/* And the rest need to be invalidated */
|
||||
noncopy_area = cairo_region_copy (window->clip_region);
|
||||
cairo_region_subtract (noncopy_area, copy_area);
|
||||
|
||||
/* convert from window coords to impl */
|
||||
cairo_region_translate (copy_area, window->abs_x, window->abs_y);
|
||||
|
||||
move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
|
||||
|
||||
/* Invalidate not copied regions */
|
||||
if (old_native_child_region)
|
||||
{
|
||||
/* No need to expose the region that the native window move copies */
|
||||
cairo_region_translate (old_native_child_region, dx, dy);
|
||||
cairo_region_intersect (old_native_child_region, new_native_child_region);
|
||||
cairo_region_subtract (noncopy_area, old_native_child_region);
|
||||
}
|
||||
gdk_window_invalidate_region_full (window, noncopy_area, TRUE, CLEAR_BG_ALL);
|
||||
|
||||
cairo_region_destroy (noncopy_area);
|
||||
cairo_region_destroy (old_layered_area);
|
||||
|
||||
if (old_native_child_region)
|
||||
{
|
||||
cairo_region_destroy (old_native_child_region);
|
||||
cairo_region_destroy (new_native_child_region);
|
||||
}
|
||||
gdk_window_invalidate_region_full (window, window->clip_region, TRUE, CLEAR_BG_ALL);
|
||||
|
||||
_gdk_synthesize_crossing_events_for_geometry_change (window);
|
||||
}
|
||||
@ -6610,9 +6369,7 @@ gdk_window_move_region (GdkWindow *window,
|
||||
gint dx,
|
||||
gint dy)
|
||||
{
|
||||
GdkWindow *impl_window;
|
||||
cairo_region_t *nocopy_area;
|
||||
cairo_region_t *copy_area;
|
||||
cairo_region_t *expose_area;
|
||||
|
||||
g_return_if_fail (GDK_IS_WINDOW (window));
|
||||
g_return_if_fail (region != NULL);
|
||||
@ -6623,36 +6380,12 @@ gdk_window_move_region (GdkWindow *window,
|
||||
if (window->destroyed)
|
||||
return;
|
||||
|
||||
impl_window = gdk_window_get_impl_window (window);
|
||||
expose_area = cairo_region_copy (region);
|
||||
cairo_region_translate (expose_area, dx, dy);
|
||||
cairo_region_union (expose_area, region);
|
||||
|
||||
/* compute source regions */
|
||||
if (gdk_window_has_alpha (window))
|
||||
copy_area = cairo_region_create (); /* Copy nothing for alpha windows */
|
||||
else
|
||||
copy_area = cairo_region_copy (region);
|
||||
cairo_region_intersect (copy_area, window->clip_region_with_children);
|
||||
cairo_region_subtract (copy_area, window->layered_region);
|
||||
remove_layered_child_area (window, copy_area);
|
||||
|
||||
/* compute destination regions */
|
||||
cairo_region_translate (copy_area, dx, dy);
|
||||
cairo_region_intersect (copy_area, window->clip_region_with_children);
|
||||
cairo_region_subtract (copy_area, window->layered_region);
|
||||
remove_layered_child_area (window, copy_area);
|
||||
|
||||
/* Invalidate parts of the region (source and dest) not covered
|
||||
by the copy */
|
||||
nocopy_area = cairo_region_copy (region);
|
||||
cairo_region_translate (nocopy_area, dx, dy);
|
||||
cairo_region_union (nocopy_area, region);
|
||||
cairo_region_subtract (nocopy_area, copy_area);
|
||||
|
||||
/* convert from window coords to impl */
|
||||
cairo_region_translate (copy_area, window->abs_x, window->abs_y);
|
||||
move_region_on_impl (impl_window, copy_area, dx, dy); /* Takes ownership of copy_area */
|
||||
|
||||
gdk_window_invalidate_region_full (window, nocopy_area, FALSE, CLEAR_BG_ALL);
|
||||
cairo_region_destroy (nocopy_area);
|
||||
gdk_window_invalidate_region_full (window, expose_area, FALSE, CLEAR_BG_ALL);
|
||||
cairo_region_destroy (expose_area);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user