diff --git a/gdk/broadway/broadway-server.c b/gdk/broadway/broadway-server.c index 3cbd214d34..bec36e3fae 100644 --- a/gdk/broadway/broadway-server.c +++ b/gdk/broadway/broadway-server.c @@ -145,6 +145,34 @@ broadway_node_free (BroadwayNode *node) g_free (node); } +gboolean +broadway_node_equal (BroadwayNode *a, + BroadwayNode *b) +{ + int i; + + if (a->hash != b->hash) + return FALSE; + + if (a->type != b->type) + return FALSE; + + if (a->n_data != b->n_data) + return FALSE; + + if (a->n_children != b->n_children) + return FALSE; + + for (i = 0; i < a->n_data; i++) + if (a->data[i] != b->data[i]) + return FALSE; + + for (i = 0; i < a->n_children; i++) + if (!broadway_node_equal (a->children[i], b->children[i])) + return FALSE; + + return TRUE; +} static void broadway_server_init (BroadwayServer *server) diff --git a/gdk/broadway/broadway-server.h b/gdk/broadway/broadway-server.h index b24fc5ed04..dba16288af 100644 --- a/gdk/broadway/broadway-server.h +++ b/gdk/broadway/broadway-server.h @@ -22,12 +22,16 @@ typedef struct _BroadwayNode BroadwayNode; struct _BroadwayNode { guint32 type; + guint32 hash; guint32 n_children; BroadwayNode **children; guint32 n_data; guint32 data[1]; }; +gboolean broadway_node_equal (BroadwayNode *a, + BroadwayNode *b); + BroadwayServer *broadway_server_new (char *address, int port, const char *ssl_cert, diff --git a/gdk/broadway/broadwayd.c b/gdk/broadway/broadwayd.c index 912a191ec7..a885a5e665 100644 --- a/gdk/broadway/broadwayd.c +++ b/gdk/broadway/broadwayd.c @@ -224,6 +224,14 @@ get_client_serial (BroadwayClient *client, guint32 daemon_serial) #define NODE_SIZE_COLOR_STOP (NODE_SIZE_FLOAT + NODE_SIZE_COLOR) #define NODE_SIZE_SHADOW (NODE_SIZE_COLOR + 3 * NODE_SIZE_FLOAT) +static guint32 +rotl (guint32 value, int shift) +{ + if ((shift &= 32 - 1) == 0) + return value; + return (value << shift) | (value >> (32 - shift)); +} + static BroadwayNode * decode_nodes (BroadwayClient *client, int len, guint32 data[], int *pos) @@ -233,6 +241,7 @@ decode_nodes (BroadwayClient *client, guint32 i, n_stops, n_shadows; guint32 size, n_children; gint32 texture_offset; + guint32 hash; g_assert (*pos < len); @@ -304,6 +313,16 @@ decode_nodes (BroadwayClient *client, for (i = 0; i < n_children; i++) node->children[i] = decode_nodes (client, len, data, pos); + hash = node->type << 16; + + for (i = 0; i < size; i++) + hash ^= rotl (node->data[i], i); + + for (i = 0; i < n_children; i++) + hash ^= rotl (node->children[i]->hash, i); + + node->hash = hash; + return node; }