From b58a366dc641b015d5ed50430fa4dfa779ad04fa Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Thu, 28 Mar 2019 20:22:44 +0100 Subject: [PATCH] broadway: Support patching nodes for textures and transforms --- gdk/broadway/broadway-output.c | 54 ++++++++++++++++++++++- gdk/broadway/broadway-protocol.h | 2 + gdk/broadway/broadway.js | 76 +++++++++++++++++++++++--------- 3 files changed, 111 insertions(+), 21 deletions(-) diff --git a/gdk/broadway/broadway-output.c b/gdk/broadway/broadway-output.c index 853a66eb85..4666acb61f 100644 --- a/gdk/broadway/broadway-output.c +++ b/gdk/broadway/broadway-output.c @@ -387,6 +387,58 @@ append_node (BroadwayOutput *output, append_node_depth--; } +static gboolean +should_reuse_node (BroadwayOutput *output, + BroadwayNode *node, + BroadwayNode *old_node) +{ + int i; + guint32 new_texture; + + if (old_node->reused) + return FALSE; + + if (node->type != old_node->type) + return FALSE; + + if (broadway_node_equal (node, old_node)) + return TRUE; + + switch (node->type) { + case BROADWAY_NODE_TRANSFORM: +#ifdef DEBUG_NODE_SENDING + g_print ("Patching transform node %d/%d\n", + old_node->id, old_node->output_id); +#endif + append_uint32 (output, BROADWAY_NODE_OP_PATCH_TRANSFORM); + append_uint32 (output, old_node->output_id); + for (i = 0; i < node->n_data; i++) + append_uint32 (output, node->data[i]); + return TRUE; + + case BROADWAY_NODE_TEXTURE: + /* Check that the size, etc is the same */ + for (i = 0; i < 4; i++) + if (node->data[i] != old_node->data[i]) + return FALSE; + + new_texture = node->data[4]; + +#ifdef DEBUG_NODE_SENDING + g_print ("Patching texture node %d/%d to tx=%d\n", + old_node->id, old_node->output_id, + new_texture); +#endif + append_uint32 (output, BROADWAY_NODE_OP_PATCH_TEXTURE); + append_uint32 (output, old_node->output_id); + append_uint32 (output, new_texture); + return TRUE; + break; + default: + return FALSE; + } +} + static BroadwayNode * append_node_ops (BroadwayOutput *output, @@ -441,7 +493,7 @@ append_node_ops (BroadwayOutput *output, * Except we avoid this for reused node as those make more sense to reuse deeply. */ - if (old_node && broadway_node_equal (node, old_node) && !old_node->reused) + if (old_node && should_reuse_node (output, node, old_node)) { int old_i = 0; BroadwayNode *last_child = NULL; diff --git a/gdk/broadway/broadway-protocol.h b/gdk/broadway/broadway-protocol.h index b642e342bc..9d1c2c03d4 100644 --- a/gdk/broadway/broadway-protocol.h +++ b/gdk/broadway/broadway-protocol.h @@ -29,6 +29,8 @@ typedef enum { /* Sync changes with broadway.js */ BROADWAY_NODE_OP_INSERT_NODE = 0, BROADWAY_NODE_OP_REMOVE_NODE = 1, BROADWAY_NODE_OP_MOVE_AFTER_CHILD = 2, + BROADWAY_NODE_OP_PATCH_TEXTURE = 3, + BROADWAY_NODE_OP_PATCH_TRANSFORM = 4, } BroadwayNodeOpType; static const char *broadway_node_type_names[] G_GNUC_UNUSED = { diff --git a/gdk/broadway/broadway.js b/gdk/broadway/broadway.js index 2cef2c1e7d..4ab39c9627 100644 --- a/gdk/broadway/broadway.js +++ b/gdk/broadway/broadway.js @@ -18,6 +18,8 @@ const BROADWAY_NODE_REUSE = 13; const BROADWAY_NODE_OP_INSERT_NODE = 0; const BROADWAY_NODE_OP_REMOVE_NODE = 1; const BROADWAY_NODE_OP_MOVE_AFTER_CHILD = 2; +const BROADWAY_NODE_OP_PATCH_TEXTURE = 3; +const BROADWAY_NODE_OP_PATCH_TRANSFORM = 4; const BROADWAY_OP_GRAB_POINTER = 'g'; const BROADWAY_OP_UNGRAB_POINTER = 'u'; @@ -67,6 +69,8 @@ const DISPLAY_OP_MOVE_NODE = 7; const DISPLAY_OP_RESIZE_NODE = 8; const DISPLAY_OP_RESTACK_SURFACES = 9; const DISPLAY_OP_DELETE_SURFACE = 10; +const DISPLAY_OP_CHANGE_TEXTURE = 11; +const DISPLAY_OP_CHANGE_TRANSFORM = 12; // GdkCrossingMode const GDK_CROSSING_NORMAL = 0; @@ -446,6 +450,28 @@ TransformNodes.prototype.decode_string = function() { return utf8_to_string (utf8); } +TransformNodes.prototype.decode_transform = function() { + var transform_type = this.decode_uint32(); + + if (transform_type == 0) { + var point = this.decode_point(); + return "translate(" + px(point.x) + "," + px(point.y) + ")"; + } else if (transform_type == 1) { + var m = new Array(); + for (var i = 0; i < 16; i++) { + m[i] = this.decode_float (); + } + + return "matrix3d(" + + m[0] + "," + m[1] + "," + m[2] + "," + m[3]+ "," + + m[4] + "," + m[5] + "," + m[6] + "," + m[7] + "," + + m[8] + "," + m[9] + "," + m[10] + "," + m[11] + "," + + m[12] + "," + m[13] + "," + m[14] + "," + m[15] + ")"; + } else { + alert("Unexpected transform type " + transform_type); + } +} + function args() { var argsLength = arguments.length; var strings = []; @@ -654,25 +680,7 @@ TransformNodes.prototype.insertNode = function(parent, previousSibling, is_tople case BROADWAY_NODE_TRANSFORM: { - var transform_type = this.decode_uint32(); - var transform_string; - - if (transform_type == 0) { - var point = this.decode_point(); - transform_string = "translate(" + px(point.x) + "," + px(point.y) + ")"; - } else if (transform_type == 1) { - var m = new Array(); - for (var i = 0; i < 16; i++) { - m[i] = this.decode_float (); - } - - transform_string = - "matrix3d(" + - m[0] + "," + m[1] + "," + m[2] + "," + m[3]+ "," + - m[4] + "," + m[5] + "," + m[6] + "," + m[7] + "," + - m[8] + "," + m[9] + "," + m[10] + "," + m[11] + "," + - m[12] + "," + m[13] + "," + m[14] + "," + m[15] + ")"; - } + var transform_string = this.decode_transform(); var div = this.createDiv(id); div.style["transform"] = transform_string; @@ -832,7 +840,21 @@ TransformNodes.prototype.execute = function(display_commands) var toMove = this.nodes[toMoveId]; this.display_commands.push([DISPLAY_OP_INSERT_AFTER_CHILD, parent, previousChild, toMove]); break; + case BROADWAY_NODE_OP_PATCH_TEXTURE: + var textureNodeId = this.decode_uint32(); + var textureNode = this.nodes[textureNodeId]; + var textureId = this.decode_uint32(); + var texture = textures[textureId].ref(); + this.display_commands.push([DISPLAY_OP_CHANGE_TEXTURE, textureNode, texture]); + break; + case BROADWAY_NODE_OP_PATCH_TRANSFORM: + var transformNodeId = this.decode_uint32(); + var transformNode = this.nodes[transformNodeId]; + var transformString = this.decode_transform(); + this.display_commands.push([DISPLAY_OP_CHANGE_TRANSFORM, transformNode, transformString]); + break; } + } } @@ -909,7 +931,21 @@ function handleDisplayCommands(display_commands) var id = cmd[1]; delete surfaces[id]; break; - + case DISPLAY_OP_CHANGE_TEXTURE: + var image = cmd[1]; + var texture = cmd[2]; + // We need a new closure here to have a separate copy of "template" for each iteration... + function a_block(t) { + image.src = t.url; + // Unref blob url when loaded + image.onload = function() { t.unref(); }; + }(texture); + break; + case DISPLAY_OP_CHANGE_TRANSFORM: + var div = cmd[1]; + var transform_string = cmd[2]; + div.style["transform"] = transform_string; + break; default: alert("Unknown display op " + command); }