mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-26 21:51:08 +00:00
broadway: Send diffs of node trees
Reusing pre-created nodes is a lot faster both in terms of dom modifications and of transfer sizes.
This commit is contained in:
parent
3d4a9324e6
commit
521b09cc96
@ -309,17 +309,61 @@ broadway_output_set_transient_for (BroadwayOutput *output,
|
||||
append_uint16 (output, parent_id);
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* This outputs the tree to the client, while at the same time diffing
|
||||
* against the old tree. This allows us to avoid sending certain
|
||||
* parts.
|
||||
*
|
||||
* Reusing existing dom nodes are problematic because doing so
|
||||
* automatically inherits all their children. There are two cases
|
||||
* where we do this:
|
||||
*
|
||||
* If the entire sub tree is identical we emit a KEEP_ALL node which
|
||||
* just reuses the entire old dom subtree.
|
||||
*
|
||||
* If a the node is unchanged (but some descendant may have changed),
|
||||
* and all parents are also unchanged, then we can just avoid
|
||||
* changing the dom node at all, and we emit a KEEP_THIS node.
|
||||
*
|
||||
***********************************/
|
||||
|
||||
static void
|
||||
append_node (BroadwayOutput *output,
|
||||
BroadwayNode *node)
|
||||
BroadwayNode *node,
|
||||
BroadwayNode *old_node,
|
||||
gboolean all_parents_are_kept)
|
||||
{
|
||||
append_uint32 (output, node->type);
|
||||
guint32 i;
|
||||
|
||||
if (old_node != NULL && broadway_node_equal (node, old_node))
|
||||
{
|
||||
if (broadway_node_deep_equal (node, old_node))
|
||||
{
|
||||
append_uint32 (output, BROADWAY_NODE_KEEP_ALL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (all_parents_are_kept)
|
||||
{
|
||||
append_uint32 (output, BROADWAY_NODE_KEEP_THIS);
|
||||
append_uint32 (output, node->n_children);
|
||||
for (i = 0; i < node->n_children; i++)
|
||||
append_node (output, node->children[i],
|
||||
i < old_node->n_children ? old_node->children[i] : NULL,
|
||||
TRUE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
append_uint32 (output, node->type);
|
||||
|
||||
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]);
|
||||
append_node (output,
|
||||
node->children[i],
|
||||
(old_node != NULL && i < old_node->n_children) ? old_node->children[i] : NULL,
|
||||
FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
@ -337,7 +381,7 @@ broadway_output_window_set_nodes (BroadwayOutput *output,
|
||||
append_uint32 (output, 0);
|
||||
|
||||
start = output->buf->len;
|
||||
append_node (output, root);
|
||||
append_node (output, root, old_root, TRUE);
|
||||
end = output->buf->len;
|
||||
patch_uint32 (output, (end - start) / 4, size_pos);
|
||||
}
|
||||
|
@ -20,6 +20,8 @@ typedef enum { /* Sync changes with broadway.js */
|
||||
BROADWAY_NODE_SHADOW = 8,
|
||||
BROADWAY_NODE_OPACITY = 9,
|
||||
BROADWAY_NODE_CLIP = 10,
|
||||
BROADWAY_NODE_KEEP_ALL = 11,
|
||||
BROADWAY_NODE_KEEP_THIS = 12,
|
||||
} BroadwayNodeType;
|
||||
|
||||
typedef enum {
|
||||
|
@ -147,33 +147,51 @@ broadway_node_free (BroadwayNode *node)
|
||||
|
||||
gboolean
|
||||
broadway_node_equal (BroadwayNode *a,
|
||||
BroadwayNode *b)
|
||||
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;
|
||||
|
||||
/* Don't check data for containers, that is just n_children, which
|
||||
we don't want to compare for a shallow equal */
|
||||
if (a->type != BROADWAY_NODE_CONTAINER)
|
||||
{
|
||||
for (i = 0; i < a->n_data; i++)
|
||||
if (a->data[i] != b->data[i])
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
broadway_node_deep_equal (BroadwayNode *a,
|
||||
BroadwayNode *b)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (a->hash != b->hash)
|
||||
return FALSE;
|
||||
|
||||
if (!broadway_node_equal (a,b))
|
||||
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]))
|
||||
if (!broadway_node_deep_equal (a->children[i], b->children[i]))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
broadway_server_init (BroadwayServer *server)
|
||||
{
|
||||
@ -1665,7 +1683,8 @@ broadway_server_window_set_nodes (BroadwayServer *server,
|
||||
|
||||
if (server->output != NULL)
|
||||
broadway_output_window_set_nodes (server->output, window->id,
|
||||
root, window->nodes);
|
||||
root,
|
||||
window->nodes);
|
||||
|
||||
if (window->nodes)
|
||||
broadway_node_free (window->nodes);
|
||||
|
@ -22,7 +22,7 @@ typedef struct _BroadwayNode BroadwayNode;
|
||||
|
||||
struct _BroadwayNode {
|
||||
guint32 type;
|
||||
guint32 hash;
|
||||
guint32 hash; /* deep hash */
|
||||
guint32 n_children;
|
||||
BroadwayNode **children;
|
||||
guint32 n_data;
|
||||
@ -30,7 +30,9 @@ struct _BroadwayNode {
|
||||
};
|
||||
|
||||
gboolean broadway_node_equal (BroadwayNode *a,
|
||||
BroadwayNode *b);
|
||||
BroadwayNode *b);
|
||||
gboolean broadway_node_deep_equal (BroadwayNode *a,
|
||||
BroadwayNode *b);
|
||||
|
||||
BroadwayServer *broadway_server_new (char *address,
|
||||
int port,
|
||||
|
@ -301,31 +301,9 @@ function SwapNodes(node_data, div) {
|
||||
this.node_data_signed = new Int32Array(node_data);
|
||||
this.data_pos = 0;
|
||||
this.div = div;
|
||||
this.div2 = document.createElement('div');
|
||||
this.outstanding = 1;
|
||||
}
|
||||
|
||||
SwapNodes.prototype.did_one = function(image) {
|
||||
this.outstanding--;
|
||||
if (this.outstanding == 0) {
|
||||
var oldDiv2 = null;
|
||||
if (this.div.hasChildNodes())
|
||||
oldDiv2 = this.div.lastChild;
|
||||
|
||||
this.div.appendChild(this.div2);
|
||||
if (oldDiv2)
|
||||
this.div.removeChild(oldDiv2);
|
||||
}
|
||||
}
|
||||
|
||||
SwapNodes.prototype.add_image = function(image) {
|
||||
this.outstanding++;
|
||||
var v = this;
|
||||
image.addEventListener('load', function() {
|
||||
v.did_one ();
|
||||
}, false);
|
||||
};
|
||||
|
||||
SwapNodes.prototype.decode_uint32 = function() {
|
||||
return this.node_data[this.data_pos++];
|
||||
}
|
||||
@ -421,26 +399,37 @@ function px(x) {
|
||||
return x + "px";
|
||||
}
|
||||
|
||||
function set_rect_style (div, rect, offset_x, offset_y) {
|
||||
div.style["left"] = px(rect.x - offset_x);
|
||||
div.style["top"] = px(rect.y - offset_y);
|
||||
function set_rect_style (div, rect) {
|
||||
div.style["left"] = px(rect.x);
|
||||
div.style["top"] = px(rect.y);
|
||||
div.style["width"] = px(rect.width);
|
||||
div.style["height"] = px(rect.height);
|
||||
}
|
||||
|
||||
function set_rrect_style (div, rrect, offset_x, offset_y) {
|
||||
set_rect_style(div, rrect.bounds, offset_x, offset_y);
|
||||
function set_rrect_style (div, rrect) {
|
||||
set_rect_style(div, rrect.bounds);
|
||||
div.style["border-top-left-radius"] = args(px(rrect.sizes[0].width), px(rrect.sizes[0].height));
|
||||
div.style["border-top-right-radius"] = args(px(rrect.sizes[1].width), px(rrect.sizes[1].height));
|
||||
div.style["border-bottom-right-radius"] = args(px(rrect.sizes[2].width), px(rrect.sizes[2].height));
|
||||
div.style["border-bottom-left-radius"] = args(px(rrect.sizes[3].width), px(rrect.sizes[3].height));
|
||||
}
|
||||
|
||||
SwapNodes.prototype.handle_node = function(parent, offset_x, offset_y)
|
||||
SwapNodes.prototype.insertNode = function(parent, posInParent, oldNode)
|
||||
{
|
||||
var type = this.decode_uint32();
|
||||
var newNode = null;
|
||||
|
||||
// We need to dup this because as we reuse children the original order is lost
|
||||
var oldChildren = [];
|
||||
if (oldNode) {
|
||||
for (var i = 0; i < oldNode.children.length; i++)
|
||||
oldChildren[i] = oldNode.children[i];
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
/* Leaf nodes */
|
||||
|
||||
case 0: // TEXTURE
|
||||
{
|
||||
var rect = this.decode_rect();
|
||||
@ -449,22 +438,10 @@ SwapNodes.prototype.handle_node = function(parent, offset_x, offset_y)
|
||||
image.width = rect.width;
|
||||
image.height = rect.height;
|
||||
image.style["position"] = "absolute";
|
||||
set_rect_style(image, rect, offset_x, offset_y);
|
||||
set_rect_style(image, rect);
|
||||
var texture_url = textures[texture_id];
|
||||
this.add_image(image);
|
||||
image.src = texture_url;
|
||||
parent.appendChild(image);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // CONTAINER
|
||||
{
|
||||
var div = document.createElement('div');
|
||||
var len = this.decode_uint32();
|
||||
for (var i = 0; i < len; i++) {
|
||||
this.handle_node(div, offset_x, offset_y);
|
||||
}
|
||||
parent.appendChild(div);
|
||||
newNode = image;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -474,9 +451,9 @@ SwapNodes.prototype.handle_node = function(parent, offset_x, offset_y)
|
||||
var c = this.decode_color ();
|
||||
var div = document.createElement('div');
|
||||
div.style["position"] = "absolute";
|
||||
set_rect_style(div, rect, offset_x, offset_y);
|
||||
set_rect_style(div, rect);
|
||||
div.style["background-color"] = c;
|
||||
parent.appendChild(div);
|
||||
newNode = div;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -494,7 +471,7 @@ SwapNodes.prototype.handle_node = function(parent, offset_x, offset_y)
|
||||
div.style["position"] = "absolute";
|
||||
rrect.bounds.width -= border_widths[1] + border_widths[3];
|
||||
rrect.bounds.height -= border_widths[0] + border_widths[2];
|
||||
set_rrect_style(div, rrect, offset_x, offset_y);
|
||||
set_rrect_style(div, rrect);
|
||||
div.style["border-style"] = "solid";
|
||||
div.style["border-top-color"] = border_colors[0];
|
||||
div.style["border-top-width"] = px(border_widths[0]);
|
||||
@ -504,7 +481,7 @@ SwapNodes.prototype.handle_node = function(parent, offset_x, offset_y)
|
||||
div.style["border-bottom-width"] = px(border_widths[2]);
|
||||
div.style["border-left-color"] = border_colors[3];
|
||||
div.style["border-left-width"] = px(border_widths[3]);
|
||||
parent.appendChild(div);
|
||||
newNode = div;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -519,9 +496,9 @@ SwapNodes.prototype.handle_node = function(parent, offset_x, offset_y)
|
||||
|
||||
var div = document.createElement('div');
|
||||
div.style["position"] = "absolute";
|
||||
set_rrect_style(div, rrect, offset_x, offset_y);
|
||||
set_rrect_style(div, rrect);
|
||||
div.style["box-shadow"] = args(px(dx), px(dy), px(blur), px(spread), color);
|
||||
parent.appendChild(div);
|
||||
newNode = div;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -536,23 +513,12 @@ SwapNodes.prototype.handle_node = function(parent, offset_x, offset_y)
|
||||
|
||||
var div = document.createElement('div');
|
||||
div.style["position"] = "absolute";
|
||||
set_rrect_style(div, rrect, offset_x, offset_y);
|
||||
set_rrect_style(div, rrect);
|
||||
div.style["box-shadow"] = args("inset", px(dx), px(dy), px(blur), px(spread), color);
|
||||
parent.appendChild(div);
|
||||
newNode = div;
|
||||
}
|
||||
break;
|
||||
|
||||
case 6: // ROUNDED_CLIP
|
||||
{
|
||||
var rrect = this.decode_rounded_rect();
|
||||
var div = document.createElement('div');
|
||||
div.style["position"] = "absolute";
|
||||
set_rrect_style(div, rrect, offset_x, offset_y);
|
||||
div.style["overflow"] = "hidden";
|
||||
parent.appendChild(div);
|
||||
this.handle_node(div, rrect.bounds.x, rrect.bounds.y);
|
||||
}
|
||||
break;
|
||||
|
||||
case 7: // LINEAR_GRADIENT
|
||||
{
|
||||
@ -562,7 +528,7 @@ SwapNodes.prototype.handle_node = function(parent, offset_x, offset_y)
|
||||
var stops = this.decode_color_stops ();
|
||||
var div = document.createElement('div');
|
||||
div.style["position"] = "absolute";
|
||||
set_rect_style(div, rect, offset_x, offset_y);
|
||||
set_rect_style(div, rect);
|
||||
|
||||
// direction:
|
||||
var dx = end.x - start.x;
|
||||
@ -595,7 +561,48 @@ SwapNodes.prototype.handle_node = function(parent, offset_x, offset_y)
|
||||
gradient = gradient + ")";
|
||||
|
||||
div.style["background-image"] = gradient;
|
||||
parent.appendChild(div);
|
||||
newNode = div;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
/* Bin nodes */
|
||||
|
||||
case 10: // CLIP
|
||||
{
|
||||
var rect = this.decode_rect();
|
||||
var div = document.createElement('div');
|
||||
div.style["position"] = "absolute";
|
||||
set_rect_style(div, rect);
|
||||
div.style["overflow"] = "hidden";
|
||||
this.insertNode(div, -1, oldChildren[0]);
|
||||
newNode = div;
|
||||
}
|
||||
break;
|
||||
|
||||
case 6: // ROUNDED_CLIP
|
||||
{
|
||||
var rrect = this.decode_rounded_rect();
|
||||
var div = document.createElement('div');
|
||||
div.style["position"] = "absolute";
|
||||
set_rrect_style(div, rrect);
|
||||
div.style["overflow"] = "hidden";
|
||||
this.insertNode(div, -1, oldChildren[0]);
|
||||
newNode = div;
|
||||
}
|
||||
break;
|
||||
|
||||
case 9: // OPACITY
|
||||
{
|
||||
var opacity = this.decode_float();
|
||||
var div = document.createElement('div');
|
||||
div.style["position"] = "absolute";
|
||||
div.style["left"] = px(0);
|
||||
div.style["top"] = px(0);
|
||||
div.style["opacity"] = opacity;
|
||||
|
||||
this.insertNode(div, -1, oldChildren[0]);
|
||||
newNode = div;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -616,40 +623,72 @@ SwapNodes.prototype.handle_node = function(parent, offset_x, offset_y)
|
||||
div.style["top"] = px(0);
|
||||
div.style["filter"] = filters;
|
||||
|
||||
parent.appendChild(div);
|
||||
this.handle_node(div, offset_x, offset_y);
|
||||
this.insertNode(div, -1, oldChildren[0]);
|
||||
newNode = div;
|
||||
}
|
||||
break;
|
||||
|
||||
case 9: // OPACITY
|
||||
{
|
||||
var opacity = this.decode_float();
|
||||
var div = document.createElement('div');
|
||||
div.style["position"] = "absolute";
|
||||
div.style["left"] = px(0);
|
||||
div.style["top"] = px(0);
|
||||
div.style["opacity"] = opacity;
|
||||
/* Generic nodes */
|
||||
|
||||
parent.appendChild(div);
|
||||
this.handle_node(div, offset_x, offset_y);
|
||||
case 1: // CONTAINER
|
||||
{
|
||||
var div = document.createElement('div');
|
||||
var len = this.decode_uint32();
|
||||
for (var i = 0; i < len; i++) {
|
||||
this.insertNode(div, -1, oldChildren[i]);
|
||||
}
|
||||
newNode = div;
|
||||
}
|
||||
break;
|
||||
|
||||
case 10: // CLIP
|
||||
case 11: // KEEP_ALL
|
||||
{
|
||||
var rect = this.decode_rect();
|
||||
var div = document.createElement('div');
|
||||
div.style["position"] = "absolute";
|
||||
set_rect_style(div, rect, offset_x, offset_y);
|
||||
div.style["overflow"] = "hidden";
|
||||
parent.appendChild(div);
|
||||
this.handle_node(div, rect.x, rect.y);
|
||||
if (!oldNode)
|
||||
alert("KEEP_ALL with no oldNode");
|
||||
|
||||
if (oldNode.parentNode != parent)
|
||||
newNode = oldNode;
|
||||
else
|
||||
newNode = null;
|
||||
}
|
||||
break;
|
||||
|
||||
case 12: // KEEP_THIS
|
||||
{
|
||||
if (!oldNode)
|
||||
alert("KEEP_THIS with no oldNode ");
|
||||
|
||||
/* We only get keep-this if all parents were kept, check this */
|
||||
if (oldNode.parentNode != parent)
|
||||
alert("Got KEEP_THIS for non-kept parent");
|
||||
|
||||
var len = this.decode_uint32();
|
||||
var i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
this.insertNode(oldNode, i,
|
||||
oldChildren[i]);
|
||||
}
|
||||
|
||||
/* Remove children that are after the new length */
|
||||
for (i = oldChildren.length - 1; i > len - 1; i--)
|
||||
oldNode.removeChild(oldChildren[i]);
|
||||
|
||||
/* NOTE: No need to modify the parent, we're keeping this node as is */
|
||||
newNode = null;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
alert("Unexpected node type " + type);
|
||||
}
|
||||
|
||||
if (newNode) {
|
||||
if (posInParent >= 0 && parent.children[posInParent])
|
||||
parent.replaceChild(newNode, parent.children[posInParent]);
|
||||
else
|
||||
parent.appendChild(newNode);
|
||||
}
|
||||
}
|
||||
|
||||
function cmdWindowSetNodes(id, node_data)
|
||||
@ -662,10 +701,9 @@ function cmdWindowSetNodes(id, node_data)
|
||||
/* We use a secondary div so that we can remove all previous children in one go */
|
||||
|
||||
var swap = new SwapNodes (node_data, div);
|
||||
swap.handle_node(swap.div2, 0, 0);
|
||||
swap.insertNode(div, 0, div.firstChild);
|
||||
if (swap.data_pos != node_data.length)
|
||||
alert ("Did not consume entire array (len " + node_data.length + " end " + end + ")");
|
||||
swap.did_one ();
|
||||
}
|
||||
|
||||
function cmdUploadTexture(id, data)
|
||||
|
@ -234,7 +234,7 @@ rotl (guint32 value, int shift)
|
||||
|
||||
static BroadwayNode *
|
||||
decode_nodes (BroadwayClient *client,
|
||||
int len, guint32 data[], int *pos)
|
||||
int len, guint32 data[], int *pos)
|
||||
{
|
||||
BroadwayNode *node;
|
||||
guint32 type;
|
||||
@ -305,9 +305,8 @@ decode_nodes (BroadwayClient *client,
|
||||
{
|
||||
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])));
|
||||
|
||||
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++)
|
||||
|
@ -116,10 +116,10 @@ add_float (GArray *nodes, float f)
|
||||
}
|
||||
|
||||
static void
|
||||
add_point (GArray *nodes, const graphene_point_t *point)
|
||||
add_point (GArray *nodes, const graphene_point_t *point, float offset_x, float offset_y)
|
||||
{
|
||||
add_float (nodes, point->x);
|
||||
add_float (nodes, point->y);
|
||||
add_float (nodes, point->x - offset_x);
|
||||
add_float (nodes, point->y - offset_y);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -130,17 +130,17 @@ add_size (GArray *nodes, const graphene_size_t *size)
|
||||
}
|
||||
|
||||
static void
|
||||
add_rect (GArray *nodes, const graphene_rect_t *rect)
|
||||
add_rect (GArray *nodes, const graphene_rect_t *rect, float offset_x, float offset_y)
|
||||
{
|
||||
add_point (nodes, &rect->origin);
|
||||
add_point (nodes, &rect->origin, offset_x, offset_y);
|
||||
add_size (nodes, &rect->size);
|
||||
}
|
||||
|
||||
static void
|
||||
add_rounded_rect (GArray *nodes, const GskRoundedRect *rrect)
|
||||
add_rounded_rect (GArray *nodes, const GskRoundedRect *rrect, float offset_x, float offset_y)
|
||||
{
|
||||
int i;
|
||||
add_rect (nodes, &rrect->bounds);
|
||||
add_rect (nodes, &rrect->bounds, offset_x, offset_y);
|
||||
for (i = 0; i < 4; i++)
|
||||
add_size (nodes, &rrect->corner[i]);
|
||||
}
|
||||
@ -461,11 +461,17 @@ node_texture_fallback (GskRenderNode *node,
|
||||
return texture;
|
||||
}
|
||||
|
||||
/* Note: This tracks the offset so that we can convert
|
||||
the absolute coordinates of the GskRenderNodes to
|
||||
parent-relative which is what the dom uses, and
|
||||
which is good for re-using subtrees. */
|
||||
static void
|
||||
gsk_broadway_renderer_add_node (GskRenderer *self,
|
||||
GArray *nodes,
|
||||
GPtrArray *node_textures,
|
||||
GskRenderNode *node)
|
||||
GskRenderNode *node,
|
||||
float offset_x,
|
||||
float offset_y)
|
||||
{
|
||||
GdkDisplay *display = gsk_renderer_get_display (self);
|
||||
|
||||
@ -475,6 +481,8 @@ gsk_broadway_renderer_add_node (GskRenderer *self,
|
||||
g_assert_not_reached ();
|
||||
return;
|
||||
|
||||
/* Leaf nodes */
|
||||
|
||||
case GSK_TEXTURE_NODE:
|
||||
{
|
||||
GdkTexture *texture = gsk_texture_node_get_texture (node);
|
||||
@ -484,10 +492,7 @@ gsk_broadway_renderer_add_node (GskRenderer *self,
|
||||
texture_id = gdk_broadway_display_ensure_texture (display, texture);
|
||||
|
||||
add_uint32 (nodes, BROADWAY_NODE_TEXTURE);
|
||||
add_float (nodes, node->bounds.origin.x);
|
||||
add_float (nodes, node->bounds.origin.y);
|
||||
add_float (nodes, gdk_texture_get_width (texture));
|
||||
add_float (nodes, gdk_texture_get_height (texture));
|
||||
add_rect (nodes, &node->bounds, offset_x, offset_y);
|
||||
add_uint32 (nodes, texture_id);
|
||||
}
|
||||
return;
|
||||
@ -495,39 +500,23 @@ gsk_broadway_renderer_add_node (GskRenderer *self,
|
||||
case GSK_CAIRO_NODE:
|
||||
{
|
||||
const cairo_surface_t *surface = gsk_cairo_node_peek_surface (node);
|
||||
GdkTexture *texture;
|
||||
GdkTexture *texture;
|
||||
guint32 texture_id;
|
||||
|
||||
texture = gdk_texture_new_for_surface ((cairo_surface_t *)surface);
|
||||
texture = gdk_texture_new_for_surface ((cairo_surface_t *)surface);
|
||||
g_ptr_array_add (node_textures, g_object_ref (texture)); /* Transfers ownership to node_textures */
|
||||
texture_id = gdk_broadway_display_ensure_texture (display, texture);
|
||||
|
||||
add_uint32 (nodes, BROADWAY_NODE_TEXTURE);
|
||||
add_float (nodes, node->bounds.origin.x);
|
||||
add_float (nodes, node->bounds.origin.y);
|
||||
add_float (nodes, node->bounds.size.width);
|
||||
add_float (nodes, node->bounds.size.height);
|
||||
add_rect (nodes, &node->bounds, offset_x, offset_y);
|
||||
add_uint32 (nodes, texture_id);
|
||||
}
|
||||
return;
|
||||
|
||||
case GSK_CONTAINER_NODE:
|
||||
{
|
||||
guint i;
|
||||
|
||||
add_uint32 (nodes, BROADWAY_NODE_CONTAINER);
|
||||
add_uint32 (nodes, gsk_container_node_get_n_children (node));
|
||||
|
||||
for (i = 0; i < gsk_container_node_get_n_children (node); i++)
|
||||
gsk_broadway_renderer_add_node (self, nodes, node_textures,
|
||||
gsk_container_node_get_child (node, i));
|
||||
}
|
||||
return;
|
||||
|
||||
case GSK_COLOR_NODE:
|
||||
{
|
||||
add_uint32 (nodes, BROADWAY_NODE_COLOR);
|
||||
add_rect (nodes, &node->bounds);
|
||||
add_rect (nodes, &node->bounds, offset_x, offset_y);
|
||||
add_rgba (nodes, gsk_color_node_peek_color (node));
|
||||
}
|
||||
return;
|
||||
@ -536,7 +525,7 @@ gsk_broadway_renderer_add_node (GskRenderer *self,
|
||||
{
|
||||
int i;
|
||||
add_uint32 (nodes, BROADWAY_NODE_BORDER);
|
||||
add_rounded_rect (nodes, gsk_border_node_peek_outline (node));
|
||||
add_rounded_rect (nodes, gsk_border_node_peek_outline (node), offset_x, offset_y);
|
||||
for (i = 0; i < 4; i++)
|
||||
add_float (nodes, gsk_border_node_peek_widths (node)[i]);
|
||||
for (i = 0; i < 4; i++)
|
||||
@ -547,7 +536,7 @@ gsk_broadway_renderer_add_node (GskRenderer *self,
|
||||
case GSK_OUTSET_SHADOW_NODE:
|
||||
{
|
||||
add_uint32 (nodes, BROADWAY_NODE_OUTSET_SHADOW);
|
||||
add_rounded_rect (nodes, gsk_outset_shadow_node_peek_outline (node));
|
||||
add_rounded_rect (nodes, gsk_outset_shadow_node_peek_outline (node), offset_x, offset_y);
|
||||
add_rgba (nodes, gsk_outset_shadow_node_peek_color (node));
|
||||
add_float (nodes, gsk_outset_shadow_node_get_dx (node));
|
||||
add_float (nodes, gsk_outset_shadow_node_get_dy (node));
|
||||
@ -559,7 +548,7 @@ gsk_broadway_renderer_add_node (GskRenderer *self,
|
||||
case GSK_INSET_SHADOW_NODE:
|
||||
{
|
||||
add_uint32 (nodes, BROADWAY_NODE_INSET_SHADOW);
|
||||
add_rounded_rect (nodes, gsk_inset_shadow_node_peek_outline (node));
|
||||
add_rounded_rect (nodes, gsk_inset_shadow_node_peek_outline (node), offset_x, offset_y);
|
||||
add_rgba (nodes, gsk_inset_shadow_node_peek_color (node));
|
||||
add_float (nodes, gsk_inset_shadow_node_get_dx (node));
|
||||
add_float (nodes, gsk_inset_shadow_node_get_dy (node));
|
||||
@ -568,23 +557,14 @@ gsk_broadway_renderer_add_node (GskRenderer *self,
|
||||
}
|
||||
return;
|
||||
|
||||
case GSK_ROUNDED_CLIP_NODE:
|
||||
{
|
||||
add_uint32 (nodes, BROADWAY_NODE_ROUNDED_CLIP);
|
||||
add_rounded_rect (nodes, gsk_rounded_clip_node_peek_clip (node));
|
||||
gsk_broadway_renderer_add_node (self, nodes, node_textures,
|
||||
gsk_rounded_clip_node_get_child (node));
|
||||
}
|
||||
return;
|
||||
|
||||
case GSK_LINEAR_GRADIENT_NODE:
|
||||
{
|
||||
guint i, n;
|
||||
|
||||
add_uint32 (nodes, BROADWAY_NODE_LINEAR_GRADIENT);
|
||||
add_rect (nodes, &node->bounds);
|
||||
add_point (nodes, gsk_linear_gradient_node_peek_start (node));
|
||||
add_point (nodes, gsk_linear_gradient_node_peek_end (node));
|
||||
add_rect (nodes, &node->bounds, offset_x, offset_y);
|
||||
add_point (nodes, gsk_linear_gradient_node_peek_start (node), offset_x, offset_y);
|
||||
add_point (nodes, gsk_linear_gradient_node_peek_end (node), offset_x, offset_y);
|
||||
n = gsk_linear_gradient_node_get_n_color_stops (node);
|
||||
add_uint32 (nodes, n);
|
||||
for (i = 0; i < n; i++)
|
||||
@ -592,6 +572,8 @@ gsk_broadway_renderer_add_node (GskRenderer *self,
|
||||
}
|
||||
return;
|
||||
|
||||
/* Bin nodes */
|
||||
|
||||
case GSK_SHADOW_NODE:
|
||||
{
|
||||
gsize i, n_shadows = gsk_shadow_node_get_n_shadows (node);
|
||||
@ -606,7 +588,8 @@ gsk_broadway_renderer_add_node (GskRenderer *self,
|
||||
add_float (nodes, shadow->radius);
|
||||
}
|
||||
gsk_broadway_renderer_add_node (self, nodes, node_textures,
|
||||
gsk_shadow_node_get_child (node));
|
||||
gsk_shadow_node_get_child (node),
|
||||
offset_x, offset_y);
|
||||
}
|
||||
return;
|
||||
|
||||
@ -615,16 +598,47 @@ gsk_broadway_renderer_add_node (GskRenderer *self,
|
||||
add_uint32 (nodes, BROADWAY_NODE_OPACITY);
|
||||
add_float (nodes, gsk_opacity_node_get_opacity (node));
|
||||
gsk_broadway_renderer_add_node (self, nodes, node_textures,
|
||||
gsk_opacity_node_get_child (node));
|
||||
gsk_opacity_node_get_child (node),
|
||||
offset_x, offset_y);
|
||||
}
|
||||
return;
|
||||
|
||||
case GSK_ROUNDED_CLIP_NODE:
|
||||
{
|
||||
const GskRoundedRect *rclip = gsk_rounded_clip_node_peek_clip (node);
|
||||
add_uint32 (nodes, BROADWAY_NODE_ROUNDED_CLIP);
|
||||
add_rounded_rect (nodes, rclip, offset_x, offset_y);
|
||||
gsk_broadway_renderer_add_node (self, nodes, node_textures,
|
||||
gsk_rounded_clip_node_get_child (node),
|
||||
rclip->bounds.origin.x,
|
||||
rclip->bounds.origin.y);
|
||||
}
|
||||
return;
|
||||
|
||||
case GSK_CLIP_NODE:
|
||||
{
|
||||
const graphene_rect_t *clip = gsk_clip_node_peek_clip (node);
|
||||
add_uint32 (nodes, BROADWAY_NODE_CLIP);
|
||||
add_rect (nodes, gsk_clip_node_peek_clip (node));
|
||||
add_rect (nodes, clip, offset_x, offset_y);
|
||||
gsk_broadway_renderer_add_node (self, nodes, node_textures,
|
||||
gsk_clip_node_get_child (node));
|
||||
gsk_clip_node_get_child (node),
|
||||
clip->origin.x,
|
||||
clip->origin.y);
|
||||
}
|
||||
return;
|
||||
|
||||
/* Generic nodes */
|
||||
|
||||
case GSK_CONTAINER_NODE:
|
||||
{
|
||||
guint i;
|
||||
|
||||
add_uint32 (nodes, BROADWAY_NODE_CONTAINER);
|
||||
add_uint32 (nodes, gsk_container_node_get_n_children (node));
|
||||
|
||||
for (i = 0; i < gsk_container_node_get_n_children (node); i++)
|
||||
gsk_broadway_renderer_add_node (self, nodes, node_textures,
|
||||
gsk_container_node_get_child (node, i), offset_x, offset_y);
|
||||
}
|
||||
return;
|
||||
|
||||
@ -643,25 +657,25 @@ gsk_broadway_renderer_add_node (GskRenderer *self,
|
||||
{
|
||||
GdkTexture *texture;
|
||||
guint32 texture_id;
|
||||
float off_x = 0, off_y = 0;
|
||||
float t_off_x = 0, t_off_y = 0;
|
||||
|
||||
texture = node_cache_lookup (node, &off_x, &off_y);
|
||||
texture = node_cache_lookup (node, &t_off_x, &t_off_y);
|
||||
|
||||
if (!texture)
|
||||
{
|
||||
texture = node_texture_fallback (node, &off_x, &off_y);
|
||||
texture = node_texture_fallback (node, &t_off_x, &t_off_y);
|
||||
#if 0
|
||||
g_print ("Fallback %p for %s\n", texture, node->node_class->type_name);
|
||||
#endif
|
||||
|
||||
node_cache_store (node, texture, off_x, off_y);
|
||||
node_cache_store (node, texture, t_off_x, t_off_y);
|
||||
}
|
||||
|
||||
g_ptr_array_add (node_textures, texture); /* Transfers ownership to node_textures */
|
||||
texture_id = gdk_broadway_display_ensure_texture (display, texture);
|
||||
add_uint32 (nodes, BROADWAY_NODE_TEXTURE);
|
||||
add_float (nodes, node->bounds.origin.x + off_x);
|
||||
add_float (nodes, node->bounds.origin.y + off_y);
|
||||
add_float (nodes, node->bounds.origin.x + t_off_x - offset_x);
|
||||
add_float (nodes, node->bounds.origin.y + t_off_y - offset_y);
|
||||
add_float (nodes, gdk_texture_get_width (texture));
|
||||
add_float (nodes, gdk_texture_get_height (texture));
|
||||
add_uint32 (nodes, texture_id);
|
||||
@ -676,7 +690,7 @@ gsk_broadway_renderer_render (GskRenderer *self,
|
||||
GArray *nodes = g_array_new (FALSE, FALSE, sizeof(guint32));
|
||||
GPtrArray *node_textures = g_ptr_array_new_with_free_func (g_object_unref);
|
||||
|
||||
gsk_broadway_renderer_add_node (self, nodes, node_textures, root);
|
||||
gsk_broadway_renderer_add_node (self, nodes, node_textures, root, 0, 0);
|
||||
gdk_broadway_window_set_nodes (window, nodes, node_textures);
|
||||
g_array_unref (nodes);
|
||||
g_ptr_array_unref (node_textures);
|
||||
|
Loading…
Reference in New Issue
Block a user