summaryrefslogtreecommitdiff
path: root/gsk
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2018-03-20 01:37:05 +0100
committerBenjamin Otte <otte@redhat.com>2018-04-05 14:56:38 +0200
commit271820b67741ff7b688dd08daa7ef8d83279189b (patch)
treef7bd9043ccfe6a3b941ff77543f9fff4bfea13a6 /gsk
parentdcdd95bbc8bd498261b50f27b0833834ebef4431 (diff)
downloadgtk+-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.c81
-rw-r--r--gsk/gskrendernodeimpl.c49
-rw-r--r--gsk/gskrendernodeprivate.h14
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,