broadway: Deserialize node tree in server

This doesn't really change anything, but it is in preparation for diffing
the trees.
This commit is contained in:
Alexander Larsson
2017-11-29 19:08:37 +01:00
parent 907e071c90
commit 1820362b2b
5 changed files with 118 additions and 54 deletions

View File

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

View File

@@ -4,6 +4,7 @@
#include <glib.h>
#include <gio/gio.h>
#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);

View File

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

View File

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

View File

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