From 48740de71a2be89fa2214890264acb4a393f6822 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 31 Oct 2023 19:07:23 -0400 Subject: [PATCH] gsk: Add a subsurface mode to node diffing Add an extra argument to pass offload info to the diffing code. This is then used for diffing subsurface nodes differently, depending on their offloading status. --- gsk/gskrenderer.c | 2 +- gsk/gskrendernode.c | 49 +++++-- gsk/gskrendernodeimpl.c | 230 ++++++++++++++++++--------------- gsk/gskrendernodeprivate.h | 19 ++- gtk/inspector/updatesoverlay.c | 2 +- 5 files changed, 179 insertions(+), 123 deletions(-) diff --git a/gsk/gskrenderer.c b/gsk/gskrenderer.c index 6db8de5dce..7ebb8a8787 100644 --- a/gsk/gskrenderer.c +++ b/gsk/gskrenderer.c @@ -444,7 +444,7 @@ gsk_renderer_render (GskRenderer *renderer, else { clip = cairo_region_copy (region); - gsk_render_node_diff (priv->prev_node, root, clip); + gsk_render_node_diff (priv->prev_node, root, clip, NULL); if (cairo_region_is_empty (clip)) { diff --git a/gsk/gskrendernode.c b/gsk/gskrendernode.c index 77c5bd5af2..8cb36425d2 100644 --- a/gsk/gskrendernode.c +++ b/gsk/gskrendernode.c @@ -154,9 +154,9 @@ gsk_render_node_real_can_diff (const GskRenderNode *node1, static void gsk_render_node_real_diff (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region) + GskDiffData *data) { - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); } static void @@ -457,14 +457,14 @@ rectangle_init_from_graphene (cairo_rectangle_int_t *cairo, void gsk_render_node_diff_impossible (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region) + GskDiffData *data) { cairo_rectangle_int_t rect; rectangle_init_from_graphene (&rect, &node1->bounds); - cairo_region_union_rectangle (region, &rect); + cairo_region_union_rectangle (data->region, &rect); rectangle_init_from_graphene (&rect, &node2->bounds); - cairo_region_union_rectangle (region, &rect); + cairo_region_union_rectangle (data->region, &rect); } /** @@ -472,6 +472,7 @@ gsk_render_node_diff_impossible (GskRenderNode *node1, * @node1: a `GskRenderNode` * @node2: the `GskRenderNode` to compare with * @region: a `cairo_region_t` to add the differences to + * @subsurfaces: (nullable): array to add offload info to * * Compares @node1 and @node2 trying to compute the minimal region of changes. * @@ -484,24 +485,48 @@ gsk_render_node_diff_impossible (GskRenderNode *node1, * * Note that the passed in @region may already contain previous results from * previous node comparisons, so this function call will only add to it. - **/ + * + * If @subsurface_nodes is not `NULL`, then we treat subsurface nodes as + * identical if they refer to the same subsurface and have the same bounds. + * In this case, we collect subsurface nodes we see in @subsurface_nodes, + * for later updating of the attached textures. + * + * If @subsurface_area is not `NULL`, it will collect the full area of all + * subsurface nodes we meet. + */ void gsk_render_node_diff (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region) + cairo_region_t *region, + GskOffload *offload) +{ + gsk_render_node_data_diff (node1, node2, &(GskDiffData) { region, offload }); +} + +void +gsk_render_node_data_diff (GskRenderNode *node1, + GskRenderNode *node2, + GskDiffData *data) { if (node1 == node2) return; if (_gsk_render_node_get_node_type (node1) == _gsk_render_node_get_node_type (node2)) - GSK_RENDER_NODE_GET_CLASS (node1)->diff (node1, node2, region); - + { + GSK_RENDER_NODE_GET_CLASS (node1)->diff (node1, node2, data); + } else if (_gsk_render_node_get_node_type (node1) == GSK_CONTAINER_NODE) - gsk_container_node_diff_with (node1, node2, region); + { + gsk_container_node_diff_with (node1, node2, data); + } else if (_gsk_render_node_get_node_type (node2) == GSK_CONTAINER_NODE) - gsk_container_node_diff_with (node2, node1, region); + { + gsk_container_node_diff_with (node2, node1, data); + } else - gsk_render_node_diff_impossible (node1, node2, region); + { + gsk_render_node_diff_impossible (node1, node2, data); + } } /** diff --git a/gsk/gskrendernodeimpl.c b/gsk/gskrendernodeimpl.c index ed545e5078..acc4b03875 100644 --- a/gsk/gskrendernodeimpl.c +++ b/gsk/gskrendernodeimpl.c @@ -31,6 +31,7 @@ #include "gskroundedrectprivate.h" #include "gskstrokeprivate.h" #include "gsktransformprivate.h" +#include "gskoffloadprivate.h" #include "gdk/gdktextureprivate.h" #include "gdk/gdkmemoryformatprivate.h" @@ -127,7 +128,7 @@ gsk_color_node_draw (GskRenderNode *node, static void gsk_color_node_diff (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region) + GskDiffData *data) { GskColorNode *self1 = (GskColorNode *) node1; GskColorNode *self2 = (GskColorNode *) node2; @@ -136,7 +137,7 @@ gsk_color_node_diff (GskRenderNode *node1, gdk_rgba_equal (&self1->color, &self2->color)) return; - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); } static void @@ -283,7 +284,7 @@ gsk_linear_gradient_node_draw (GskRenderNode *node, static void gsk_linear_gradient_node_diff (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region) + GskDiffData *data) { GskLinearGradientNode *self1 = (GskLinearGradientNode *) node1; GskLinearGradientNode *self2 = (GskLinearGradientNode *) node2; @@ -303,14 +304,14 @@ gsk_linear_gradient_node_diff (GskRenderNode *node1, gdk_rgba_equal (&stop1->color, &stop2->color)) continue; - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); return; } return; } - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); } static void @@ -612,7 +613,7 @@ gsk_radial_gradient_node_draw (GskRenderNode *node, static void gsk_radial_gradient_node_diff (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region) + GskDiffData *data) { GskRadialGradientNode *self1 = (GskRadialGradientNode *) node1; GskRadialGradientNode *self2 = (GskRadialGradientNode *) node2; @@ -635,14 +636,14 @@ gsk_radial_gradient_node_diff (GskRenderNode *node1, gdk_rgba_equal (&stop1->color, &stop2->color)) continue; - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); return; } return; } - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); } static void @@ -1103,7 +1104,7 @@ gsk_conic_gradient_node_draw (GskRenderNode *node, static void gsk_conic_gradient_node_diff (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region) + GskDiffData *data) { GskConicGradientNode *self1 = (GskConicGradientNode *) node1; GskConicGradientNode *self2 = (GskConicGradientNode *) node2; @@ -1113,7 +1114,7 @@ gsk_conic_gradient_node_diff (GskRenderNode *node1, self1->rotation != self2->rotation || self1->n_stops != self2->n_stops) { - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); return; } @@ -1125,7 +1126,7 @@ gsk_conic_gradient_node_diff (GskRenderNode *node1, if (stop1->offset != stop2->offset || !gdk_rgba_equal (&stop1->color, &stop2->color)) { - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); return; } } @@ -1455,7 +1456,7 @@ gsk_border_node_draw (GskRenderNode *node, static void gsk_border_node_diff (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region) + GskDiffData *data) { GskBorderNode *self1 = (GskBorderNode *) node1; GskBorderNode *self2 = (GskBorderNode *) node2; @@ -1472,7 +1473,7 @@ gsk_border_node_diff (GskRenderNode *node1, /* Different uniformity -> diff impossible */ if (uniform1 ^ uniform2) { - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); return; } @@ -1487,7 +1488,7 @@ gsk_border_node_diff (GskRenderNode *node1, gsk_rounded_rect_equal (&self1->outline, &self2->outline)) return; - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); } static void @@ -1680,7 +1681,7 @@ gsk_texture_node_draw (GskRenderNode *node, static void gsk_texture_node_diff (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region) + GskDiffData *data) { GskTextureNode *self1 = (GskTextureNode *) node1; GskTextureNode *self2 = (GskTextureNode *) node2; @@ -1690,7 +1691,7 @@ gsk_texture_node_diff (GskRenderNode *node1, gdk_texture_get_width (self1->texture) != gdk_texture_get_width (self2->texture) || gdk_texture_get_height (self1->texture) != gdk_texture_get_height (self2->texture)) { - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); return; } @@ -1699,7 +1700,7 @@ gsk_texture_node_diff (GskRenderNode *node1, sub = cairo_region_create (); gdk_texture_diff (self1->texture, self2->texture, sub); - region_union_region_affine (region, + region_union_region_affine (data->region, sub, node1->bounds.size.width / gdk_texture_get_width (self1->texture), node1->bounds.size.height / gdk_texture_get_height (self1->texture), @@ -1867,7 +1868,7 @@ gsk_texture_scale_node_draw (GskRenderNode *node, static void gsk_texture_scale_node_diff (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region) + GskDiffData *data) { GskTextureScaleNode *self1 = (GskTextureScaleNode *) node1; GskTextureScaleNode *self2 = (GskTextureScaleNode *) node2; @@ -1878,7 +1879,7 @@ gsk_texture_scale_node_diff (GskRenderNode *node1, gdk_texture_get_width (self1->texture) != gdk_texture_get_width (self2->texture) || gdk_texture_get_height (self1->texture) != gdk_texture_get_height (self2->texture)) { - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); return; } @@ -1887,7 +1888,7 @@ gsk_texture_scale_node_diff (GskRenderNode *node1, sub = cairo_region_create (); gdk_texture_diff (self1->texture, self2->texture, sub); - region_union_region_affine (region, + region_union_region_affine (data->region, sub, node1->bounds.size.width / gdk_texture_get_width (self1->texture), node1->bounds.size.height / gdk_texture_get_height (self1->texture), @@ -2390,7 +2391,7 @@ gsk_inset_shadow_node_draw (GskRenderNode *node, static void gsk_inset_shadow_node_diff (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region) + GskDiffData *data) { GskInsetShadowNode *self1 = (GskInsetShadowNode *) node1; GskInsetShadowNode *self2 = (GskInsetShadowNode *) node2; @@ -2403,7 +2404,7 @@ gsk_inset_shadow_node_diff (GskRenderNode *node1, self1->blur_radius == self2->blur_radius) return; - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); } static void @@ -2703,7 +2704,7 @@ gsk_outset_shadow_node_draw (GskRenderNode *node, static void gsk_outset_shadow_node_diff (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region) + GskDiffData *data) { GskOutsetShadowNode *self1 = (GskOutsetShadowNode *) node1; GskOutsetShadowNode *self2 = (GskOutsetShadowNode *) node2; @@ -2716,7 +2717,7 @@ gsk_outset_shadow_node_diff (GskRenderNode *node1, self1->blur_radius == self2->blur_radius) return; - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); } static void @@ -3083,8 +3084,10 @@ gsk_container_node_compare_func (gconstpointer elem1, gconstpointer elem2, gpoin static GskDiffResult gsk_container_node_keep_func (gconstpointer elem1, gconstpointer elem2, gpointer data) { - gsk_render_node_diff ((GskRenderNode *) elem1, (GskRenderNode *) elem2, data); - if (cairo_region_num_rectangles (data) > MAX_RECTS_IN_DIFF) + GskDiffData *gd = data; + + gsk_render_node_data_diff ((GskRenderNode *) elem1, (GskRenderNode *) elem2, gd); + if (cairo_region_num_rectangles (gd->region) > MAX_RECTS_IN_DIFF) return GSK_DIFF_ABORTED; return GSK_DIFF_OK; @@ -3094,12 +3097,12 @@ static GskDiffResult gsk_container_node_change_func (gconstpointer elem, gsize idx, gpointer data) { const GskRenderNode *node = elem; - cairo_region_t *region = data; + GskDiffData *gd = data; cairo_rectangle_int_t rect; rectangle_init_from_graphene (&rect, &node->bounds); - cairo_region_union_rectangle (region, &rect); - if (cairo_region_num_rectangles (region) > MAX_RECTS_IN_DIFF) + cairo_region_union_rectangle (gd->region, &rect); + if (cairo_region_num_rectangles (gd->region) > MAX_RECTS_IN_DIFF) return GSK_DIFF_ABORTED; return GSK_DIFF_OK; @@ -3127,18 +3130,18 @@ gsk_render_node_diff_multiple (GskRenderNode **nodes1, gsize n_nodes1, GskRenderNode **nodes2, gsize n_nodes2, - cairo_region_t *region) + GskDiffData *data) { return gsk_diff ((gconstpointer *) nodes1, n_nodes1, (gconstpointer *) nodes2, n_nodes2, gsk_container_node_get_diff_settings (), - region) == GSK_DIFF_OK; + data) == GSK_DIFF_OK; } void gsk_container_node_diff_with (GskRenderNode *container, GskRenderNode *other, - cairo_region_t *region) + GskDiffData *data) { GskContainerNode *self = (GskContainerNode *) container; @@ -3146,16 +3149,16 @@ gsk_container_node_diff_with (GskRenderNode *container, self->n_children, &other, 1, - region)) + data)) return; - gsk_render_node_diff_impossible (container, other, region); + gsk_render_node_diff_impossible (container, other, data); } static void gsk_container_node_diff (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region) + GskDiffData *data) { GskContainerNode *self1 = (GskContainerNode *) node1; GskContainerNode *self2 = (GskContainerNode *) node2; @@ -3164,10 +3167,10 @@ gsk_container_node_diff (GskRenderNode *node1, self1->n_children, self2->children, self2->n_children, - region)) + data)) return; - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); } static void @@ -3387,14 +3390,14 @@ gsk_transform_node_can_diff (const GskRenderNode *node1, static void gsk_transform_node_diff (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region) + GskDiffData *data) { GskTransformNode *self1 = (GskTransformNode *) node1; GskTransformNode *self2 = (GskTransformNode *) node2; if (!gsk_transform_equal (self1->transform, self2->transform)) { - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); return; } @@ -3404,7 +3407,7 @@ gsk_transform_node_diff (GskRenderNode *node1, switch (gsk_transform_get_category (self1->transform)) { case GSK_TRANSFORM_CATEGORY_IDENTITY: - gsk_render_node_diff (self1->child, self2->child, region); + gsk_render_node_data_diff (self1->child, self2->child, data); break; case GSK_TRANSFORM_CATEGORY_2D_TRANSLATE: @@ -3413,7 +3416,7 @@ gsk_transform_node_diff (GskRenderNode *node1, float dx, dy; gsk_transform_to_translate (self1->transform, &dx, &dy); sub = cairo_region_create (); - gsk_render_node_diff (self1->child, self2->child, sub); + gsk_render_node_data_diff (self1->child, self2->child, &(GskDiffData) {sub, data->offload }); cairo_region_translate (sub, floorf (dx), floorf (dy)); if (floorf (dx) != dx) { @@ -3429,7 +3432,7 @@ gsk_transform_node_diff (GskRenderNode *node1, cairo_region_union (sub, tmp); cairo_region_destroy (tmp); } - cairo_region_union (region, sub); + cairo_region_union (data->region, sub); cairo_region_destroy (sub); } break; @@ -3440,8 +3443,8 @@ gsk_transform_node_diff (GskRenderNode *node1, float scale_x, scale_y, dx, dy; gsk_transform_to_affine (self1->transform, &scale_x, &scale_y, &dx, &dy); sub = cairo_region_create (); - gsk_render_node_diff (self1->child, self2->child, sub); - region_union_region_affine (region, sub, scale_x, scale_y, dx, dy); + gsk_render_node_data_diff (self1->child, self2->child, &(GskDiffData) { sub, data->offload }); + region_union_region_affine (data->region, sub, scale_x, scale_y, dx, dy); cairo_region_destroy (sub); } break; @@ -3451,7 +3454,7 @@ gsk_transform_node_diff (GskRenderNode *node1, case GSK_TRANSFORM_CATEGORY_3D: case GSK_TRANSFORM_CATEGORY_2D: default: - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); break; } } @@ -3606,15 +3609,15 @@ gsk_opacity_node_draw (GskRenderNode *node, static void gsk_opacity_node_diff (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region) + GskDiffData *data) { GskOpacityNode *self1 = (GskOpacityNode *) node1; GskOpacityNode *self2 = (GskOpacityNode *) node2; if (self1->opacity == self2->opacity) - gsk_render_node_diff (self1->child, self2->child, region); + gsk_render_node_data_diff (self1->child, self2->child, data); else - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); } static void @@ -3821,7 +3824,7 @@ gsk_color_matrix_node_draw (GskRenderNode *node, static void gsk_color_matrix_node_diff (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region) + GskDiffData *data) { GskColorMatrixNode *self1 = (GskColorMatrixNode *) node1; GskColorMatrixNode *self2 = (GskColorMatrixNode *) node2; @@ -3832,11 +3835,11 @@ gsk_color_matrix_node_diff (GskRenderNode *node1, if (!graphene_matrix_equal_fast (&self1->color_matrix, &self2->color_matrix)) goto nope; - gsk_render_node_diff (self1->child, self2->child, region); + gsk_render_node_data_diff (self1->child, self2->child, data); return; nope: - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); return; } @@ -4141,7 +4144,7 @@ gsk_clip_node_draw (GskRenderNode *node, static void gsk_clip_node_diff (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region) + GskDiffData *data) { GskClipNode *self1 = (GskClipNode *) node1; GskClipNode *self2 = (GskClipNode *) node2; @@ -4152,15 +4155,15 @@ gsk_clip_node_diff (GskRenderNode *node1, cairo_rectangle_int_t clip_rect; sub = cairo_region_create(); - gsk_render_node_diff (self1->child, self2->child, sub); + gsk_render_node_data_diff (self1->child, self2->child, &(GskDiffData) {sub, data->offload }); rectangle_init_from_graphene (&clip_rect, &self1->clip); cairo_region_intersect_rectangle (sub, &clip_rect); - cairo_region_union (region, sub); + cairo_region_union (data->region, sub); cairo_region_destroy (sub); } else { - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); } } @@ -4289,7 +4292,7 @@ gsk_rounded_clip_node_draw (GskRenderNode *node, static void gsk_rounded_clip_node_diff (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region) + GskDiffData *data) { GskRoundedClipNode *self1 = (GskRoundedClipNode *) node1; GskRoundedClipNode *self2 = (GskRoundedClipNode *) node2; @@ -4300,15 +4303,15 @@ gsk_rounded_clip_node_diff (GskRenderNode *node1, cairo_rectangle_int_t clip_rect; sub = cairo_region_create(); - gsk_render_node_diff (self1->child, self2->child, sub); + gsk_render_node_data_diff (self1->child, self2->child, &(GskDiffData) { sub, data->offload }); rectangle_init_from_graphene (&clip_rect, &self1->clip.bounds); cairo_region_intersect_rectangle (sub, &clip_rect); - cairo_region_union (region, sub); + cairo_region_union (data->region, sub); cairo_region_destroy (sub); } else { - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); } } @@ -4463,7 +4466,7 @@ gsk_fill_node_draw (GskRenderNode *node, static void gsk_fill_node_diff (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region) + GskDiffData *data) { GskFillNode *self1 = (GskFillNode *) node1; GskFillNode *self2 = (GskFillNode *) node2; @@ -4474,15 +4477,15 @@ gsk_fill_node_diff (GskRenderNode *node1, cairo_rectangle_int_t clip_rect; sub = cairo_region_create(); - gsk_render_node_diff (self1->child, self2->child, sub); + gsk_render_node_data_diff (self1->child, self2->child, &(GskDiffData) { sub, data->offload }); rectangle_init_from_graphene (&clip_rect, &node1->bounds); cairo_region_intersect_rectangle (sub, &clip_rect); - cairo_region_union (region, sub); + cairo_region_union (data->region, sub); cairo_region_destroy (sub); } else { - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); } } @@ -4667,7 +4670,7 @@ gsk_stroke_node_draw (GskRenderNode *node, static void gsk_stroke_node_diff (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region) + GskDiffData *data) { GskStrokeNode *self1 = (GskStrokeNode *) node1; GskStrokeNode *self2 = (GskStrokeNode *) node2; @@ -4679,15 +4682,15 @@ gsk_stroke_node_diff (GskRenderNode *node1, cairo_rectangle_int_t clip_rect; sub = cairo_region_create(); - gsk_render_node_diff (self1->child, self2->child, sub); + gsk_render_node_data_diff (self1->child, self2->child, &(GskDiffData) { sub, data->offload }); rectangle_init_from_graphene (&clip_rect, &node1->bounds); cairo_region_intersect_rectangle (sub, &clip_rect); - cairo_region_union (region, sub); + cairo_region_union (data->region, sub); cairo_region_destroy (sub); } else { - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); } } @@ -4883,7 +4886,7 @@ gsk_shadow_node_draw (GskRenderNode *node, static void gsk_shadow_node_diff (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region) + GskDiffData *data) { GskShadowNode *self1 = (GskShadowNode *) node1; GskShadowNode *self2 = (GskShadowNode *) node2; @@ -4894,7 +4897,7 @@ gsk_shadow_node_diff (GskRenderNode *node1, if (self1->n_shadows != self2->n_shadows) { - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); return; } @@ -4909,7 +4912,7 @@ gsk_shadow_node_diff (GskRenderNode *node1, shadow1->dy != shadow2->dy || shadow1->radius != shadow2->radius) { - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); return; } @@ -4921,7 +4924,7 @@ gsk_shadow_node_diff (GskRenderNode *node1, } sub = cairo_region_create (); - gsk_render_node_diff (self1->child, self2->child, sub); + gsk_render_node_data_diff (self1->child, self2->child, &(GskDiffData) { sub, data->offload }); n = cairo_region_num_rectangles (sub); for (i = 0; i < n; i++) @@ -4931,7 +4934,7 @@ gsk_shadow_node_diff (GskRenderNode *node1, rect.y -= top; rect.width += left + right; rect.height += top + bottom; - cairo_region_union_rectangle (region, &rect); + cairo_region_union_rectangle (data->region, &rect); } cairo_region_destroy (sub); } @@ -5156,19 +5159,19 @@ gsk_blend_node_draw (GskRenderNode *node, static void gsk_blend_node_diff (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region) + GskDiffData *data) { GskBlendNode *self1 = (GskBlendNode *) node1; GskBlendNode *self2 = (GskBlendNode *) node2; if (self1->blend_mode == self2->blend_mode) { - gsk_render_node_diff (self1->top, self2->top, region); - gsk_render_node_diff (self1->bottom, self2->bottom, region); + gsk_render_node_data_diff (self1->top, self2->top, data); + gsk_render_node_data_diff (self1->bottom, self2->bottom, data); } else { - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); } } @@ -5323,19 +5326,19 @@ gsk_cross_fade_node_draw (GskRenderNode *node, static void gsk_cross_fade_node_diff (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region) + GskDiffData *data) { GskCrossFadeNode *self1 = (GskCrossFadeNode *) node1; GskCrossFadeNode *self2 = (GskCrossFadeNode *) node2; if (self1->progress == self2->progress) { - gsk_render_node_diff (self1->start, self2->start, region); - gsk_render_node_diff (self1->end, self2->end, region); + gsk_render_node_data_diff (self1->start, self2->start, data); + gsk_render_node_data_diff (self1->end, self2->end, data); return; } - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); } static void @@ -5494,7 +5497,7 @@ gsk_text_node_draw (GskRenderNode *node, static void gsk_text_node_diff (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region) + GskDiffData *data) { GskTextNode *self1 = (GskTextNode *) node1; GskTextNode *self2 = (GskTextNode *) node2; @@ -5519,14 +5522,14 @@ gsk_text_node_diff (GskRenderNode *node1, info1->attr.is_color == info2->attr.is_color) continue; - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); return; } return; } - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); } static void @@ -5932,7 +5935,7 @@ gsk_blur_node_draw (GskRenderNode *node, static void gsk_blur_node_diff (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region) + GskDiffData *data) { GskBlurNode *self1 = (GskBlurNode *) node1; GskBlurNode *self2 = (GskBlurNode *) node2; @@ -5945,7 +5948,7 @@ gsk_blur_node_diff (GskRenderNode *node1, clip_radius = ceil (gsk_cairo_blur_compute_pixels (self1->radius / 2.0)); sub = cairo_region_create (); - gsk_render_node_diff (self1->child, self2->child, sub); + gsk_render_node_data_diff (self1->child, self2->child, &(GskDiffData) {sub, data->offload }); n = cairo_region_num_rectangles (sub); for (i = 0; i < n; i++) @@ -5955,13 +5958,13 @@ gsk_blur_node_diff (GskRenderNode *node1, rect.y -= clip_radius; rect.width += 2 * clip_radius; rect.height += 2 * clip_radius; - cairo_region_union_rectangle (region, &rect); + cairo_region_union_rectangle (data->region, &rect); } cairo_region_destroy (sub); } else { - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); } } @@ -6176,19 +6179,19 @@ gsk_mask_node_draw (GskRenderNode *node, static void gsk_mask_node_diff (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region) + GskDiffData *data) { GskMaskNode *self1 = (GskMaskNode *) node1; GskMaskNode *self2 = (GskMaskNode *) node2; if (self1->mask_mode != self2->mask_mode) { - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); return; } - gsk_render_node_diff (self1->source, self2->source, region); - gsk_render_node_diff (self1->mask, self2->mask, region); + gsk_render_node_data_diff (self1->source, self2->source, data); + gsk_render_node_data_diff (self1->mask, self2->mask, data); } static void @@ -6351,12 +6354,12 @@ gsk_debug_node_can_diff (const GskRenderNode *node1, static void gsk_debug_node_diff (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region) + GskDiffData *data) { GskDebugNode *self1 = (GskDebugNode *) node1; GskDebugNode *self2 = (GskDebugNode *) node2; - gsk_render_node_diff (self1->child, self2->child, region); + gsk_render_node_data_diff (self1->child, self2->child, data); } static void @@ -6487,7 +6490,7 @@ gsk_gl_shader_node_draw (GskRenderNode *node, static void gsk_gl_shader_node_diff (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region) + GskDiffData *data) { GskGLShaderNode *self1 = (GskGLShaderNode *) node1; GskGLShaderNode *self2 = (GskGLShaderNode *) node2; @@ -6499,14 +6502,14 @@ gsk_gl_shader_node_diff (GskRenderNode *node1, { cairo_region_t *child_region = cairo_region_create(); for (guint i = 0; i < self1->n_children; i++) - gsk_render_node_diff (self1->children[i], self2->children[i], child_region); + gsk_render_node_data_diff (self1->children[i], self2->children[i], &(GskDiffData) {child_region, data->offload }); if (!cairo_region_is_empty (child_region)) - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); cairo_region_destroy (child_region); } else { - gsk_render_node_diff_impossible (node1, node2, region); + gsk_render_node_diff_impossible (node1, node2, data); } } @@ -6701,23 +6704,40 @@ static gboolean gsk_subsurface_node_can_diff (const GskRenderNode *node1, const GskRenderNode *node2) { - return TRUE; + GskSubsurfaceNode *self1 = (GskSubsurfaceNode *) node1; + GskSubsurfaceNode *self2 = (GskSubsurfaceNode *) node2; + + return self1->subsurface == self2->subsurface; } static void gsk_subsurface_node_diff (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region) + GskDiffData *data) { GskSubsurfaceNode *self1 = (GskSubsurfaceNode *) node1; GskSubsurfaceNode *self2 = (GskSubsurfaceNode *) node2; - if (gdk_subsurface_get_texture (self1->subsurface) != NULL && - self1->subsurface == self2->subsurface && - graphene_rect_equal (&node1->bounds, &node2->bounds)) - return; - - return gsk_render_node_diff (self1->child, self2->child, region); + if (data->offload) + { + /* Include the full area if the offload status changed. */ + if (gsk_offload_subsurface_was_offloaded (data->offload, self1->subsurface) != + gsk_offload_subsurface_is_offloaded (data->offload, self1->subsurface)) + { + gsk_render_node_diff_impossible (node1, node2, data); + } + else if (gsk_offload_subsurface_is_offloaded (data->offload, self1->subsurface)) + { + if (!gsk_rect_equal (&node1->bounds, &node2->bounds)) + gsk_render_node_diff_impossible (node1, node2, data); + } + else + { + gsk_render_node_data_diff (self1->child, self2->child, data); + } + } + else + gsk_render_node_data_diff (self1->child, self2->child, data); } static void diff --git a/gsk/gskrendernodeprivate.h b/gsk/gskrendernodeprivate.h index 20ac0396d0..93dc460d5b 100644 --- a/gsk/gskrendernodeprivate.h +++ b/gsk/gskrendernodeprivate.h @@ -1,6 +1,7 @@ #pragma once #include "gskrendernode.h" +#include "gskoffloadprivate.h" #include #include "gdk/gdkmemoryformatprivate.h" @@ -36,6 +37,12 @@ struct _GskRenderNode guint offscreen_for_opacity : 1; }; +typedef struct +{ + cairo_region_t *region; + GskOffload *offload; +} GskDiffData; + struct _GskRenderNodeClass { GTypeClass parent_class; @@ -49,7 +56,7 @@ struct _GskRenderNodeClass const GskRenderNode *node2); void (* diff) (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region); + GskDiffData *data); }; void gsk_render_node_init_types (void); @@ -66,13 +73,17 @@ gboolean gsk_render_node_can_diff (const GskRenderNode const GskRenderNode *node2) G_GNUC_PURE; void gsk_render_node_diff (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region); + cairo_region_t *region, + GskOffload *offload); +void gsk_render_node_data_diff (GskRenderNode *node1, + GskRenderNode *node2, + GskDiffData *data); void gsk_render_node_diff_impossible (GskRenderNode *node1, GskRenderNode *node2, - cairo_region_t *region); + GskDiffData *data); void gsk_container_node_diff_with (GskRenderNode *container, GskRenderNode *other, - cairo_region_t *region); + GskDiffData *data); bool gsk_border_node_get_uniform (const GskRenderNode *self); bool gsk_border_node_get_uniform_color (const GskRenderNode *self); diff --git a/gtk/inspector/updatesoverlay.c b/gtk/inspector/updatesoverlay.c index 002f47cd9c..542dc59a71 100644 --- a/gtk/inspector/updatesoverlay.c +++ b/gtk/inspector/updatesoverlay.c @@ -183,7 +183,7 @@ gtk_updates_overlay_snapshot (GtkInspectorOverlay *overlay, cairo_region_t *diff; diff = cairo_region_create (); - gsk_render_node_diff (updates->last, node, diff); + gsk_render_node_diff (updates->last, node, diff, NULL); if (cairo_region_is_empty (diff)) cairo_region_destroy (diff); else