From 1820362b2b419a3185f030dcab3a0f90bae06cbb Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Wed, 29 Nov 2017 19:08:37 +0100 Subject: [PATCH] broadway: Deserialize node tree in server This doesn't really change anything, but it is in preparation for diffing the trees. --- gdk/broadway/broadway-output.c | 35 ++++++++++--- gdk/broadway/broadway-output.h | 4 +- gdk/broadway/broadway-server.c | 31 ++++++++---- gdk/broadway/broadway-server.h | 12 ++++- gdk/broadway/broadwayd.c | 90 +++++++++++++++++++++------------- 5 files changed, 118 insertions(+), 54 deletions(-) diff --git a/gdk/broadway/broadway-output.c b/gdk/broadway/broadway-output.c index 036f71b0fa..e679923f37 100644 --- a/gdk/broadway/broadway-output.c +++ b/gdk/broadway/broadway-output.c @@ -296,19 +296,42 @@ broadway_output_set_transient_for (BroadwayOutput *output, append_uint16 (output, parent_id); } +static void +append_node (BroadwayOutput *output, + BroadwayNode *node) +{ + append_uint32 (output, node->type); + guint32 i; + + for (i = 0; i < node->n_data; i++) + append_uint32 (output, node->data[i]); + for (i = 0; i < node->n_children; i++) + append_node (output, node->children[i]); +} + +guint32 +get_node_size (BroadwayNode *node) +{ + guint32 size = 1 + node->n_data; + guint32 i; + + for (i = 0; i < node->n_children; i++) + size += get_node_size (node->children[i]); + + return size; +} + + void broadway_output_window_set_nodes (BroadwayOutput *output, int id, - guint32 *data, - guint32 data_len) + BroadwayNode *root) { write_header (output, BROADWAY_OP_SET_NODES); - guint32 i; append_uint16 (output, id); - append_uint32 (output, data_len); - for (i = 0; i < data_len; i++) - append_uint32 (output, data[i]); + append_uint32 (output, get_node_size (root)); + append_node (output, root); } void diff --git a/gdk/broadway/broadway-output.h b/gdk/broadway/broadway-output.h index bf35be2aec..db1ba944d8 100644 --- a/gdk/broadway/broadway-output.h +++ b/gdk/broadway/broadway-output.h @@ -4,6 +4,7 @@ #include #include #include "broadway-protocol.h" +#include "broadway-server.h" typedef struct BroadwayOutput BroadwayOutput; @@ -58,8 +59,7 @@ void broadway_output_set_transient_for (BroadwayOutput *output, int parent_id); void broadway_output_window_set_nodes (BroadwayOutput *output, int id, - guint32 *data, - guint32 data_len); + BroadwayNode *root); void broadway_output_upload_texture (BroadwayOutput *output, guint32 id, GBytes *texture); diff --git a/gdk/broadway/broadway-server.c b/gdk/broadway/broadway-server.c index 3f9dfebc16..a6b311415c 100644 --- a/gdk/broadway/broadway-server.c +++ b/gdk/broadway/broadway-server.c @@ -125,8 +125,7 @@ struct BroadwayWindow { gboolean visible; gint32 transient_for; guint32 texture; - guint32 *nodes; - gint nodes_len; + BroadwayNode *nodes; }; static void broadway_server_resync_windows (BroadwayServer *server); @@ -136,6 +135,17 @@ static GType broadway_server_get_type (void); G_DEFINE_TYPE (BroadwayServer, broadway_server, G_TYPE_OBJECT) +static void +broadway_node_free (BroadwayNode *node) +{ + int i; + for (i = 0; i < node->n_children; i++) + broadway_node_free (node->children[i]); + + g_free (node); +} + + static void broadway_server_init (BroadwayServer *server) { @@ -187,7 +197,8 @@ broadway_server_class_init (BroadwayServerClass * class) static void broadway_window_free (BroadwayWindow *window) { - g_free (window->nodes); + if (window->nodes) + broadway_node_free (window->nodes); g_free (window); } @@ -1612,11 +1623,11 @@ broadway_server_has_client (BroadwayServer *server) return server->output != NULL; } +/* passes ownership of nodes */ void broadway_server_window_set_nodes (BroadwayServer *server, gint id, - gint n_data, - guint32 *data) + BroadwayNode *root) { BroadwayWindow *window; @@ -1624,13 +1635,13 @@ broadway_server_window_set_nodes (BroadwayServer *server, if (window == NULL) return; - g_free (window->nodes); - window->nodes = g_memdup (data, sizeof (guint32)*n_data); - window->nodes_len = n_data; + if (window->nodes) + broadway_node_free (window->nodes); + window->nodes = root; if (server->output != NULL) broadway_output_window_set_nodes (server->output, window->id, - window->nodes, window->nodes_len); + window->nodes); } guint32 @@ -1877,7 +1888,7 @@ broadway_server_resync_windows (BroadwayServer *server) if (window->nodes) broadway_output_window_set_nodes (server->output, window->id, - window->nodes, window->nodes_len); + window->nodes); if (window->visible) broadway_output_show_surface (server->output, window->id); diff --git a/gdk/broadway/broadway-server.h b/gdk/broadway/broadway-server.h index d120261181..b24fc5ed04 100644 --- a/gdk/broadway/broadway-server.h +++ b/gdk/broadway/broadway-server.h @@ -18,6 +18,15 @@ typedef struct _BroadwayServerClass BroadwayServerClass; #define BROADWAY_IS_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), BROADWAY_TYPE_SERVER)) #define BROADWAY_SERVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), BROADWAY_TYPE_SERVER, BroadwayServerClass)) +typedef struct _BroadwayNode BroadwayNode; + +struct _BroadwayNode { + guint32 type; + guint32 n_children; + BroadwayNode **children; + guint32 n_data; + guint32 data[1]; +}; BroadwayServer *broadway_server_new (char *address, int port, @@ -87,8 +96,7 @@ cairo_surface_t * broadway_server_create_surface (int int height); void broadway_server_window_set_nodes (BroadwayServer *server, gint id, - gint n_data, - guint32 *data); + BroadwayNode *root); gboolean broadway_server_window_move_resize (BroadwayServer *server, gint id, gboolean with_move, diff --git a/gdk/broadway/broadwayd.c b/gdk/broadway/broadwayd.c index 638b7f9b16..912a191ec7 100644 --- a/gdk/broadway/broadwayd.c +++ b/gdk/broadway/broadwayd.c @@ -224,66 +224,88 @@ 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 int -rewrite_node_textures (BroadwayClient *client, - int len, guint32 data[], int pos) +static BroadwayNode * +decode_nodes (BroadwayClient *client, + int len, guint32 data[], int *pos) { + BroadwayNode *node; guint32 type; - guint32 i, n_children, n_stops, n_shadows; + guint32 i, n_stops, n_shadows; + guint32 size, n_children; + gint32 texture_offset; - g_assert (pos < len); + g_assert (*pos < len); - type = data[pos++]; + size = 0; + n_children = 0; + texture_offset = -1; + + type = data[(*pos)++]; switch (type) { case BROADWAY_NODE_COLOR: - pos += NODE_SIZE_RECT + NODE_SIZE_COLOR; + size = NODE_SIZE_RECT + NODE_SIZE_COLOR; break; case BROADWAY_NODE_BORDER: - pos += NODE_SIZE_RRECT + 4 * NODE_SIZE_FLOAT + 4 * NODE_SIZE_COLOR; + size = NODE_SIZE_RRECT + 4 * NODE_SIZE_FLOAT + 4 * NODE_SIZE_COLOR; break; case BROADWAY_NODE_INSET_SHADOW: case BROADWAY_NODE_OUTSET_SHADOW: - pos += NODE_SIZE_RRECT + NODE_SIZE_COLOR + 4 * NODE_SIZE_FLOAT; + size = NODE_SIZE_RRECT + NODE_SIZE_COLOR + 4 * NODE_SIZE_FLOAT; break; case BROADWAY_NODE_TEXTURE: - data[pos+4] = GPOINTER_TO_INT (g_hash_table_lookup (client->textures, - GINT_TO_POINTER (data[pos+4]))); - pos += 5; + texture_offset = 4; + size = 5; break; case BROADWAY_NODE_CONTAINER: - n_children = data[pos++]; - for (i = 0; i < n_children; i++) - pos = rewrite_node_textures (client, len, data, pos); + size = 1; + n_children = data[*pos]; break; case BROADWAY_NODE_ROUNDED_CLIP: - pos += NODE_SIZE_RRECT; - pos = rewrite_node_textures (client, len, data, pos); + size = NODE_SIZE_RRECT; + n_children = 1; break; case BROADWAY_NODE_CLIP: - pos += NODE_SIZE_RECT; - pos = rewrite_node_textures (client, len, data, pos); + size = NODE_SIZE_RECT; + n_children = 1; break; case BROADWAY_NODE_LINEAR_GRADIENT: - pos += NODE_SIZE_RECT + 2 * NODE_SIZE_POINT; - n_stops = data[pos++]; - pos += n_stops * NODE_SIZE_COLOR_STOP; + size = NODE_SIZE_RECT + 2 * NODE_SIZE_POINT; + n_stops = data[*pos + size++]; + size += n_stops * NODE_SIZE_COLOR_STOP; break; case BROADWAY_NODE_SHADOW: - n_shadows = data[pos++]; - pos += n_shadows * NODE_SIZE_SHADOW; - pos = rewrite_node_textures (client, len, data, pos); + size = 1; + n_shadows = data[*pos]; + size += n_shadows * NODE_SIZE_SHADOW; + n_children = 1; break; case BROADWAY_NODE_OPACITY: - pos += NODE_SIZE_FLOAT; - pos = rewrite_node_textures (client, len, data, pos); + size = NODE_SIZE_FLOAT; + n_children = 1; break; default: g_assert_not_reached (); } - return pos; -} + node = g_malloc (sizeof(BroadwayNode) + (size - 1) * sizeof(guint32) + n_children * sizeof (BroadwayNode *)); + node->type = type; + node->n_children = n_children; + node->children = (BroadwayNode **)((char *)node + sizeof(BroadwayNode) + (size - 1) * sizeof(guint32)); + node->n_data = size; + for (i = 0; i < size; i++) + { + node->data[i] = data[(*pos)++]; + if (i == texture_offset) + node->data[i] = GPOINTER_TO_INT (g_hash_table_lookup (client->textures, + GINT_TO_POINTER (node->data[i]))); + } + + for (i = 0; i < n_children; i++) + node->children[i] = decode_nodes (client, len, data, pos); + + return node; +} static void client_handle_request (BroadwayClient *client, @@ -360,13 +382,13 @@ client_handle_request (BroadwayClient *client, { gsize array_size = request->base.size - sizeof (BroadwayRequestSetNodes) + sizeof(guint32); int n_data = array_size / sizeof(guint32); + int pos = 0; + BroadwayNode *node; - rewrite_node_textures (client, n_data, request->set_nodes.data, 0); + node = decode_nodes (client, n_data, request->set_nodes.data, &pos); - broadway_server_window_set_nodes (server, - request->set_nodes.id, - n_data, - request->set_nodes.data); + broadway_server_window_set_nodes (server, request->set_nodes.id, + node); } break; case BROADWAY_REQUEST_UPLOAD_TEXTURE: