From: Benjamin Otte Date: Wed, 28 Mar 2018 14:42:26 +0000 (+0200) Subject: widget: Stop tracking invalidations X-Git-Tag: archive/raspbian/4.4.1+ds1-2+rpi1^2~18^2~22^2~672 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=a468714849358b6de1d26834c0d0e24cce0892e2;p=gtk4.git widget: Stop tracking invalidations Instead of calling gdk_surface_invalidate_region(), just gdk_surface_queue_expose() and rely on the renderer computing the diff from the previous rendering. --- diff --git a/docs/reference/gdk/gdk4-sections.txt b/docs/reference/gdk/gdk4-sections.txt index 2bbbc4fa23..784615d1ea 100644 --- a/docs/reference/gdk/gdk4-sections.txt +++ b/docs/reference/gdk/gdk4-sections.txt @@ -240,6 +240,7 @@ gdk_surface_end_draw_frame gdk_surface_invalidate_rect gdk_surface_invalidate_region +gdk_surface_queue_expose gdk_surface_freeze_updates gdk_surface_thaw_updates gdk_surface_get_frame_clock diff --git a/gdk/gdksurface.c b/gdk/gdksurface.c index ea1f3fe654..bc12fd589d 100644 --- a/gdk/gdksurface.c +++ b/gdk/gdksurface.c @@ -129,8 +129,6 @@ static void recompute_visible_regions (GdkSurface *private, static void gdk_surface_invalidate_in_parent (GdkSurface *private); static void update_cursor (GdkDisplay *display, GdkDevice *device); -static void impl_surface_add_update_area (GdkSurface *impl_surface, - cairo_region_t *region); static cairo_surface_t *gdk_surface_ref_impl_surface (GdkSurface *surface); static void gdk_surface_set_frame_clock (GdkSurface *surface, @@ -2202,7 +2200,7 @@ gdk_surface_invalidate_rect (GdkSurface *surface, } static void -impl_surface_add_update_area (GdkSurface *impl_surface, +impl_surface_add_update_area (GdkSurface *impl_surface, cairo_region_t *region) { if (impl_surface->update_area) @@ -2215,6 +2213,33 @@ impl_surface_add_update_area (GdkSurface *impl_surface, } } +/** + * gdk_surface_queue_expose: + * @surface: a #GdkSurface + * + * Forces an expose event for @surface to be scheduled. + * + * If the invalid area of @surface is empty, an expose event will + * still be emitted. Its invalid region will be empty. + * + * This function is useful for implementations that track invalid + * regions on their own. + **/ +void +gdk_surface_queue_expose (GdkSurface *surface) +{ + cairo_region_t *region; + + g_return_if_fail (GDK_IS_SURFACE (surface)); + + while (!gdk_surface_has_impl (surface)) + surface = surface->parent; + + region = cairo_region_create (); + impl_surface_add_update_area (surface, region); + cairo_region_destroy (region); +} + /** * gdk_surface_invalidate_region: * @surface: a #GdkSurface diff --git a/gdk/gdksurface.h b/gdk/gdksurface.h index 0da93cb879..bed9bb04e3 100644 --- a/gdk/gdksurface.h +++ b/gdk/gdksurface.h @@ -803,6 +803,8 @@ void gdk_surface_begin_move_drag_for_device (GdkSurface *surface, /* Interface for dirty-region queueing */ GDK_AVAILABLE_IN_ALL +void gdk_surface_queue_expose (GdkSurface *surface); +GDK_AVAILABLE_IN_ALL void gdk_surface_invalidate_rect (GdkSurface *surface, const GdkRectangle *rect); GDK_AVAILABLE_IN_ALL diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index 92c8084cd5..77cafe4890 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -3977,49 +3977,6 @@ gtk_widget_get_surface_allocation (GtkWidget *widget, *allocation = alloc; } -/** - * gtk_widget_queue_draw_area: - * @widget: a #GtkWidget - * @x: x coordinate of upper-left corner of rectangle to redraw - * @y: y coordinate of upper-left corner of rectangle to redraw - * @width: width of region to draw - * @height: height of region to draw - * - * Convenience function that calls gtk_widget_queue_draw_region() on - * the region created from the given coordinates. - * - * The region here is specified in widget coordinates of @widget. - * - * @width or @height may be 0, in this case this function does - * nothing. Negative values for @width and @height are not allowed. - */ -void -gtk_widget_queue_draw_area (GtkWidget *widget, - gint x, - gint y, - gint width, - gint height) -{ - GdkRectangle rect; - cairo_region_t *region; - - g_return_if_fail (GTK_IS_WIDGET (widget)); - g_return_if_fail (width >= 0); - g_return_if_fail (height >= 0); - - if (width == 0 || height == 0) - return; - - rect.x = x; - rect.y = y; - rect.width = width; - rect.height = height; - - region = cairo_region_create_rectangle (&rect); - gtk_widget_queue_draw_region (widget, region); - cairo_region_destroy (region); -} - static void gtk_widget_invalidate_paintable_contents (GtkWidget *widget) { @@ -4056,9 +4013,44 @@ gtk_widget_real_queue_draw (GtkWidget *widget) priv->draw_needed = TRUE; g_clear_pointer (&priv->render_node, gsk_render_node_unref); gtk_widget_invalidate_paintable_contents (widget); + if (_gtk_widget_get_has_surface (widget) && + _gtk_widget_get_realized (widget)) + gdk_surface_queue_expose (gtk_widget_get_surface (widget)); } } +/** + * gtk_widget_queue_draw_area: + * @widget: a #GtkWidget + * @x: x coordinate of upper-left corner of rectangle to redraw + * @y: y coordinate of upper-left corner of rectangle to redraw + * @width: width of region to draw + * @height: height of region to draw + * + * Convenience function that calls gtk_widget_queue_draw_region() on + * the region created from the given coordinates. + * + * The region here is specified in widget coordinates of @widget. + * + * @width or @height may be 0, in this case this function does + * nothing. Negative values for @width and @height are not allowed. + */ +void +gtk_widget_queue_draw_area (GtkWidget *widget, + gint x, + gint y, + gint width, + gint height) +{ + g_return_if_fail (GTK_IS_WIDGET (widget)); + + /* Just return if the widget isn't mapped */ + if (!_gtk_widget_get_mapped (widget)) + return; + + gtk_widget_real_queue_draw (widget); +} + /** * gtk_widget_queue_draw: * @widget: a #GtkWidget @@ -4069,22 +4061,13 @@ gtk_widget_real_queue_draw (GtkWidget *widget) void gtk_widget_queue_draw (GtkWidget *widget) { - GtkWidget *parent; - GdkRectangle *rect; - g_return_if_fail (GTK_IS_WIDGET (widget)); - gtk_widget_real_queue_draw (widget); - - parent = _gtk_widget_get_parent (widget); - rect = &widget->priv->clip; + /* Just return if the widget isn't mapped */ + if (!_gtk_widget_get_mapped (widget)) + return; - if (!_gtk_widget_get_has_surface (widget)) - gtk_widget_queue_draw_area (parent ? parent : widget, - rect->x, rect->y, rect->width, rect->height); - else - gtk_widget_queue_draw_area (widget, - 0, 0, rect->width, rect->height); + gtk_widget_real_queue_draw (widget); } static void @@ -4314,85 +4297,15 @@ void gtk_widget_queue_draw_region (GtkWidget *widget, const cairo_region_t *region) { - GtkWidget *windowed_parent; - cairo_rectangle_int_t self_clip; - cairo_region_t *clip_region = NULL; - cairo_region_t *region2; - int x, y; - GtkCssStyle *parent_style; - GtkBorder border, padding; - g_return_if_fail (GTK_IS_WIDGET (widget)); - if (cairo_region_is_empty (region)) - return; - /* Just return if the widget isn't mapped */ if (!_gtk_widget_get_mapped (widget)) return; gtk_widget_real_queue_draw (widget); - - if (!_gtk_widget_get_parent (widget)) - { - g_assert (_gtk_widget_get_has_surface (widget)); - region2 = cairo_region_copy (region); - windowed_parent = widget; - goto invalidate; - } - - /* priv->clip is in parent coordinates, transform it to @widget coordinates. */ - self_clip = widget->priv->clip; - self_clip.x -= widget->priv->allocation.x; - self_clip.y -= widget->priv->allocation.y; - clip_region = cairo_region_create_rectangle (&self_clip); - - region2 = cairo_region_copy (region); - cairo_region_intersect (region2, clip_region); - - /* Look for the parent with a window and invalidate @region in there. */ - windowed_parent = widget; - while (windowed_parent != NULL && !_gtk_widget_get_has_surface (windowed_parent)) - windowed_parent = _gtk_widget_get_parent (windowed_parent); - - g_assert (windowed_parent != NULL); - - /* @region's coordinates are originally relative to @widget's origin */ - if (widget != windowed_parent) - gtk_widget_translate_coordinates (widget, - windowed_parent, - 0, 0, - &x, &y); - else - x = y = 0; - - /* At this point, x and y are relative to the windowed parent's origin, - * but the window of the parent spans over its entire allocation, so we need - * to account for border and padding manually. The values returned from - * gtk_widget_get_surface_allocation, which should've been used to size and position - * @parent's window, do not include widget margins nor css margins. - */ - parent_style = gtk_css_node_get_style (windowed_parent->priv->cssnode); - get_box_border (parent_style, &border); - get_box_padding (parent_style, &padding); - - x += border.left + padding.left; - y += border.top + padding.top; - - cairo_region_translate (region2, x, y); - -invalidate: - gdk_surface_invalidate_region (_gtk_widget_get_surface (widget), region2); - - cairo_region_destroy (region2); - - if (clip_region) - cairo_region_destroy (clip_region); } - - - /** * gtk_widget_size_allocate: * @widget: a #GtkWidget