diff options
author | Benjamin Otte <otte@redhat.com> | 2018-03-20 01:37:05 +0100 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2018-04-05 14:56:38 +0200 |
commit | 271820b67741ff7b688dd08daa7ef8d83279189b (patch) | |
tree | f7bd9043ccfe6a3b941ff77543f9fff4bfea13a6 /gsk | |
parent | dcdd95bbc8bd498261b50f27b0833834ebef4431 (diff) | |
download | gtk+-271820b67741ff7b688dd08daa7ef8d83279189b.tar.gz |
rendernode: Add gsk_render_node_diff()
... and gsk_render_node_can_diff(). Those are vfuncs to compute a region
containing all the pixels that differ between the two nodes.
This is just the plumbing that chains into node classes. No node
implements it yet.
Diffstat (limited to 'gsk')
-rw-r--r-- | gsk/gskrendernode.c | 81 | ||||
-rw-r--r-- | gsk/gskrendernodeimpl.c | 49 | ||||
-rw-r--r-- | gsk/gskrendernodeprivate.h | 14 |
3 files changed, 144 insertions, 0 deletions
diff --git a/gsk/gskrendernode.c b/gsk/gskrendernode.c index 5c7af11493..da858b71e9 100644 --- a/gsk/gskrendernode.c +++ b/gsk/gskrendernode.c @@ -266,6 +266,87 @@ gsk_render_node_draw (GskRenderNode *node, } } +/* + * gsk_render_node_can_diff: + * @node1: a #GskRenderNode + * @node2: the #GskRenderNode to compare with + * + * Checks if 2 render nodes can be expected to be compared via + * gsk_render_node_diff(). The node diffing algorithm uses this function + * to match up similar nodes to compare when trying to minimze the + * resulting region. + * + * Nodes of different type always return %FALSE here. + * + * Returns: %TRUE if @node1 and @node2 can be expected to be compared + **/ +gboolean +gsk_render_node_can_diff (GskRenderNode *node1, + GskRenderNode *node2) +{ + if (node1 == node2) + return TRUE; + + if (gsk_render_node_get_node_type (node1) != gsk_render_node_get_node_type (node2)) + return FALSE; + + return node1->node_class->can_diff (node1, node2); +} + +static void +rectangle_init_from_graphene (cairo_rectangle_int_t *cairo, + const graphene_rect_t *graphene) +{ + cairo->x = floorf (graphene->origin.x); + cairo->y = floorf (graphene->origin.y); + cairo->width = ceilf (graphene->origin.x + graphene->size.width) - cairo->x; + cairo->height = ceilf (graphene->origin.y + graphene->size.height) - cairo->y; +} + +void +gsk_render_node_diff_impossible (GskRenderNode *node1, + GskRenderNode *node2, + cairo_region_t *region) +{ + cairo_rectangle_int_t rect; + + rectangle_init_from_graphene (&rect, &node1->bounds); + cairo_region_union_rectangle (region, &rect); + rectangle_init_from_graphene (&rect, &node2->bounds); + cairo_region_union_rectangle (region, &rect); +} + +/** + * gsk_render_node_diff: + * @node1: a #GskRenderNode + * @node2: the #GskRenderNode to compare with + * @region: a #cairo_region_t to add the differences to + * + * Compares @node1 and @node2 trying to compute the minimal region of changes. + * In the worst case, this is the union of the bounds of @node1 and @node2. + * + * This function is used to compute the area that needs to be redrawn when + * the previous contents were drawn by @node1 and the new contents should + * correspond to @node2. As such, it is important that this comparison is + * faster than the time it takes to actually do the redraw. + * + * Note that the passed in @region may already contain previous results from + * previous node comparisons, so this function call will only add to it. + **/ +void +gsk_render_node_diff (GskRenderNode *node1, + GskRenderNode *node2, + cairo_region_t *region) +{ + if (node1 == node2) + return; + + if (gsk_render_node_get_node_type (node1) != gsk_render_node_get_node_type (node2)) + return gsk_render_node_diff_impossible (node1, node2, region); + + return node1->node_class->diff (node1, node2, region); +} + #define GSK_RENDER_NODE_SERIALIZATION_VERSION 0 #define GSK_RENDER_NODE_SERIALIZATION_ID "GskRenderNode" diff --git a/gsk/gskrendernodeimpl.c b/gsk/gskrendernodeimpl.c index 3a3a7d783c..15f9479d85 100644 --- a/gsk/gskrendernodeimpl.c +++ b/gsk/gskrendernodeimpl.c @@ -43,6 +43,13 @@ check_variant_type (GVariant *variant, return TRUE; } +static gboolean +gsk_render_node_can_diff_impossible (GskRenderNode *node1, + GskRenderNode *node2) +{ + return FALSE; +} + /*** GSK_COLOR_NODE ***/ typedef struct _GskColorNode GskColorNode; @@ -110,6 +117,8 @@ static const GskRenderNodeClass GSK_COLOR_NODE_CLASS = { "GskColorNode", gsk_color_node_finalize, gsk_color_node_draw, + gsk_render_node_can_diff_impossible, + gsk_render_node_diff_impossible, gsk_color_node_serialize, gsk_color_node_deserialize, }; @@ -286,6 +295,8 @@ static const GskRenderNodeClass GSK_LINEAR_GRADIENT_NODE_CLASS = { "GskLinearGradientNode", gsk_linear_gradient_node_finalize, gsk_linear_gradient_node_draw, + gsk_render_node_can_diff_impossible, + gsk_render_node_diff_impossible, gsk_linear_gradient_node_serialize, gsk_linear_gradient_node_deserialize, }; @@ -296,6 +307,8 @@ static const GskRenderNodeClass GSK_REPEATING_LINEAR_GRADIENT_NODE_CLASS = { "GskRepeatingLinearGradientNode", gsk_linear_gradient_node_finalize, gsk_linear_gradient_node_draw, + gsk_render_node_can_diff_impossible, + gsk_render_node_diff_impossible, gsk_linear_gradient_node_serialize, gsk_repeating_linear_gradient_node_deserialize, }; @@ -585,6 +598,8 @@ static const GskRenderNodeClass GSK_BORDER_NODE_CLASS = { "GskBorderNode", gsk_border_node_finalize, gsk_border_node_draw, + gsk_render_node_can_diff_impossible, + gsk_render_node_diff_impossible, gsk_border_node_serialize, gsk_border_node_deserialize }; @@ -772,6 +787,8 @@ static const GskRenderNodeClass GSK_TEXTURE_NODE_CLASS = { "GskTextureNode", gsk_texture_node_finalize, gsk_texture_node_draw, + gsk_render_node_can_diff_impossible, + gsk_render_node_diff_impossible, gsk_texture_node_serialize, gsk_texture_node_deserialize }; @@ -1278,6 +1295,8 @@ static const GskRenderNodeClass GSK_INSET_SHADOW_NODE_CLASS = { "GskInsetShadowNode", gsk_inset_shadow_node_finalize, gsk_inset_shadow_node_draw, + gsk_render_node_can_diff_impossible, + gsk_render_node_diff_impossible, gsk_inset_shadow_node_serialize, gsk_inset_shadow_node_deserialize }; @@ -1579,6 +1598,8 @@ static const GskRenderNodeClass GSK_OUTSET_SHADOW_NODE_CLASS = { "GskOutsetShadowNode", gsk_outset_shadow_node_finalize, gsk_outset_shadow_node_draw, + gsk_render_node_can_diff_impossible, + gsk_render_node_diff_impossible, gsk_outset_shadow_node_serialize, gsk_outset_shadow_node_deserialize }; @@ -1846,6 +1867,8 @@ static const GskRenderNodeClass GSK_CAIRO_NODE_CLASS = { "GskCairoNode", gsk_cairo_node_finalize, gsk_cairo_node_draw, + gsk_render_node_can_diff_impossible, + gsk_render_node_diff_impossible, gsk_cairo_node_serialize, gsk_cairo_node_deserialize }; @@ -2075,6 +2098,8 @@ static const GskRenderNodeClass GSK_CONTAINER_NODE_CLASS = { "GskContainerNode", gsk_container_node_finalize, gsk_container_node_draw, + gsk_render_node_can_diff_impossible, + gsk_render_node_diff_impossible, gsk_container_node_serialize, gsk_container_node_deserialize }; @@ -2258,6 +2283,8 @@ static const GskRenderNodeClass GSK_TRANSFORM_NODE_CLASS = { "GskTransformNode", gsk_transform_node_finalize, gsk_transform_node_draw, + gsk_render_node_can_diff_impossible, + gsk_render_node_diff_impossible, gsk_transform_node_serialize, gsk_transform_node_deserialize }; @@ -2400,6 +2427,8 @@ static const GskRenderNodeClass GSK_OFFSET_NODE_CLASS = { "GskOffsetNode", gsk_offset_node_finalize, gsk_offset_node_draw, + gsk_render_node_can_diff_impossible, + gsk_render_node_diff_impossible, gsk_offset_node_serialize, gsk_offset_node_deserialize }; @@ -2569,6 +2598,8 @@ static const GskRenderNodeClass GSK_OPACITY_NODE_CLASS = { "GskOpacityNode", gsk_opacity_node_finalize, gsk_opacity_node_draw, + gsk_render_node_can_diff_impossible, + gsk_render_node_diff_impossible, gsk_opacity_node_serialize, gsk_opacity_node_deserialize }; @@ -2804,6 +2835,8 @@ static const GskRenderNodeClass GSK_COLOR_MATRIX_NODE_CLASS = { "GskColorMatrixNode", gsk_color_matrix_node_finalize, gsk_color_matrix_node_draw, + gsk_render_node_can_diff_impossible, + gsk_render_node_diff_impossible, gsk_color_matrix_node_serialize, gsk_color_matrix_node_deserialize }; @@ -2992,6 +3025,8 @@ static const GskRenderNodeClass GSK_REPEAT_NODE_CLASS = { "GskRepeatNode", gsk_repeat_node_finalize, gsk_repeat_node_draw, + gsk_render_node_can_diff_impossible, + gsk_render_node_diff_impossible, gsk_repeat_node_serialize, gsk_repeat_node_deserialize }; @@ -3137,6 +3172,8 @@ static const GskRenderNodeClass GSK_CLIP_NODE_CLASS = { "GskClipNode", gsk_clip_node_finalize, gsk_clip_node_draw, + gsk_render_node_can_diff_impossible, + gsk_render_node_diff_impossible, gsk_clip_node_serialize, gsk_clip_node_deserialize }; @@ -3298,6 +3335,8 @@ static const GskRenderNodeClass GSK_ROUNDED_CLIP_NODE_CLASS = { "GskRoundedClipNode", gsk_rounded_clip_node_finalize, gsk_rounded_clip_node_draw, + gsk_render_node_can_diff_impossible, + gsk_render_node_diff_impossible, gsk_rounded_clip_node_serialize, gsk_rounded_clip_node_deserialize }; @@ -3521,6 +3560,8 @@ static const GskRenderNodeClass GSK_SHADOW_NODE_CLASS = { "GskShadowNode", gsk_shadow_node_finalize, gsk_shadow_node_draw, + gsk_render_node_can_diff_impossible, + gsk_render_node_diff_impossible, gsk_shadow_node_serialize, gsk_shadow_node_deserialize }; @@ -3735,6 +3776,8 @@ static const GskRenderNodeClass GSK_BLEND_NODE_CLASS = { "GskBlendNode", gsk_blend_node_finalize, gsk_blend_node_draw, + gsk_render_node_can_diff_impossible, + gsk_render_node_diff_impossible, gsk_blend_node_serialize, gsk_blend_node_deserialize }; @@ -3905,6 +3948,8 @@ static const GskRenderNodeClass GSK_CROSS_FADE_NODE_CLASS = { "GskCrossFadeNode", gsk_cross_fade_node_finalize, gsk_cross_fade_node_draw, + gsk_render_node_can_diff_impossible, + gsk_render_node_diff_impossible, gsk_cross_fade_node_serialize, gsk_cross_fade_node_deserialize }; @@ -4126,6 +4171,8 @@ static const GskRenderNodeClass GSK_TEXT_NODE_CLASS = { "GskTextNode", gsk_text_node_finalize, gsk_text_node_draw, + gsk_render_node_can_diff_impossible, + gsk_render_node_diff_impossible, gsk_text_node_serialize, gsk_text_node_deserialize }; @@ -4511,6 +4558,8 @@ static const GskRenderNodeClass GSK_BLUR_NODE_CLASS = { "GskBlurNode", gsk_blur_node_finalize, gsk_blur_node_draw, + gsk_render_node_can_diff_impossible, + gsk_render_node_diff_impossible, gsk_blur_node_serialize, gsk_blur_node_deserialize }; diff --git a/gsk/gskrendernodeprivate.h b/gsk/gskrendernodeprivate.h index dad1703e0b..5cae3ec562 100644 --- a/gsk/gskrendernodeprivate.h +++ b/gsk/gskrendernodeprivate.h @@ -31,6 +31,11 @@ struct _GskRenderNodeClass void (* finalize) (GskRenderNode *node); void (* draw) (GskRenderNode *node, cairo_t *cr); + gboolean (* can_diff) (GskRenderNode *node1, + GskRenderNode *node2); + void (* diff) (GskRenderNode *node1, + GskRenderNode *node2, + cairo_region_t *region); GVariant * (* serialize) (GskRenderNode *node); GskRenderNode * (* deserialize) (GVariant *variant, GError **error); @@ -39,6 +44,15 @@ struct _GskRenderNodeClass GskRenderNode * gsk_render_node_new (const GskRenderNodeClass *node_class, gsize extra_size); +gboolean gsk_render_node_can_diff (GskRenderNode *node1, + GskRenderNode *node2); +void gsk_render_node_diff (GskRenderNode *node1, + GskRenderNode *node2, + cairo_region_t *region); +void gsk_render_node_diff_impossible (GskRenderNode *node1, + GskRenderNode *node2, + cairo_region_t *region); + GVariant * gsk_render_node_serialize_node (GskRenderNode *node); GskRenderNode * gsk_render_node_deserialize_node (GskRenderNodeType type, GVariant *variant, |