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.
This commit is contained in:
Matthias Clasen 2023-10-31 19:07:23 -04:00
parent 34c16b0df2
commit 48740de71a
5 changed files with 179 additions and 123 deletions

View File

@ -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))
{

View File

@ -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);
}
}
/**

View File

@ -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

View File

@ -1,6 +1,7 @@
#pragma once
#include "gskrendernode.h"
#include "gskoffloadprivate.h"
#include <cairo.h>
#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);

View File

@ -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