From: Benjamin Otte Date: Tue, 20 Mar 2018 01:46:57 +0000 (+0100) Subject: rendernode: Add an offset node X-Git-Tag: archive/raspbian/4.4.1+ds1-2+rpi1^2~18^2~22^2~796 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=ce743f28a19a1d33fee9311c131791c4bb332596;p=gtk4.git rendernode: Add an offset node This is a special case of the transform node that does a 2D translation. The implementation in the Vulkan and GL renderers is crude and just does the same as the transform node. Nothing uses that node yet. --- diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c index 42abb0343d..ba37952225 100644 --- a/gsk/gl/gskglrenderer.c +++ b/gsk/gl/gskglrenderer.c @@ -622,6 +622,29 @@ render_texture_node (GskGLRenderer *self, } } +static inline void +render_offset_node (GskGLRenderer *self, + GskRenderNode *node, + RenderOpBuilder *builder) +{ + GskRenderNode *child = gsk_offset_node_get_child (node); + graphene_matrix_t prev_mv; + graphene_matrix_t transform, transformed_mv; + + graphene_matrix_init_translate (&transform, + &GRAPHENE_POINT3D_INIT( + gsk_offset_node_get_x_offset (node), + gsk_offset_node_get_y_offset (node), + 1.0 + )); + graphene_matrix_multiply (&transform, &builder->current_modelview, &transformed_mv); + prev_mv = ops_set_modelview (builder, &transformed_mv); + + gsk_gl_renderer_add_render_ops (self, child, builder); + + ops_set_modelview (builder, &prev_mv); +} + static inline void render_transform_node (GskGLRenderer *self, GskRenderNode *node, @@ -2110,6 +2133,10 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self, render_texture_node (self, node, builder); break; + case GSK_OFFSET_NODE: + render_offset_node (self, node, builder); + break; + case GSK_TRANSFORM_NODE: render_transform_node (self, node, builder); break; diff --git a/gsk/gskbroadwayrenderer.c b/gsk/gskbroadwayrenderer.c index 5e3b763d10..3e997fd3f3 100644 --- a/gsk/gskbroadwayrenderer.c +++ b/gsk/gskbroadwayrenderer.c @@ -645,6 +645,7 @@ gsk_broadway_renderer_add_node (GskRenderer *self, case GSK_COLOR_MATRIX_NODE: case GSK_TEXT_NODE: case GSK_REPEATING_LINEAR_GRADIENT_NODE: + case GSK_OFFSET_NODE: case GSK_TRANSFORM_NODE: case GSK_REPEAT_NODE: case GSK_BLEND_NODE: diff --git a/gsk/gskenums.h b/gsk/gskenums.h index 5c20ef39d9..9835774152 100644 --- a/gsk/gskenums.h +++ b/gsk/gskenums.h @@ -35,6 +35,7 @@ * @GSK_INSET_SHADOW_NODE: A node drawing an inset shadow * @GSK_OUTSET_SHADOW_NODE: A node drawing an outset shadow * @GSK_TRANSFORM_NODE: A node that renders its child after applying a matrix transform + * @GSK_OFFSET_NODE: A node that renders its child after applying a 2D translation * @GSK_OPACITY_NODE: A node that changes the opacity of its child * @GSK_COLOR_MATRIX_NODE: A node that applies a color matrix to every pixel * @GSK_REPEAT_NODE: A node that repeats the child's contents @@ -62,6 +63,7 @@ typedef enum { GSK_INSET_SHADOW_NODE, GSK_OUTSET_SHADOW_NODE, GSK_TRANSFORM_NODE, + GSK_OFFSET_NODE, GSK_OPACITY_NODE, GSK_COLOR_MATRIX_NODE, GSK_REPEAT_NODE, diff --git a/gsk/gskrendernode.h b/gsk/gskrendernode.h index 8c8717d96d..e7604d6b65 100644 --- a/gsk/gskrendernode.h +++ b/gsk/gskrendernode.h @@ -200,6 +200,17 @@ GDK_AVAILABLE_IN_ALL const graphene_matrix_t * gsk_transform_node_peek_transform (GskRenderNode *node); +GDK_AVAILABLE_IN_ALL +GskRenderNode * gsk_offset_node_new (GskRenderNode *child, + double x, + double y); +GDK_AVAILABLE_IN_ALL +GskRenderNode * gsk_offset_node_get_child (GskRenderNode *node); +GDK_AVAILABLE_IN_ALL +double gsk_offset_node_get_x_offset (GskRenderNode *node); +GDK_AVAILABLE_IN_ALL +double gsk_offset_node_get_y_offset (GskRenderNode *node); + GDK_AVAILABLE_IN_ALL GskRenderNode * gsk_opacity_node_new (GskRenderNode *child, double opacity); diff --git a/gsk/gskrendernodeimpl.c b/gsk/gskrendernodeimpl.c index 51ae14cd42..347a4e1333 100644 --- a/gsk/gskrendernodeimpl.c +++ b/gsk/gskrendernodeimpl.c @@ -2320,6 +2320,164 @@ gsk_transform_node_peek_transform (GskRenderNode *node) return &self->transform; } +/*** GSK_OFFSET_NODE ***/ + +typedef struct _GskOffsetNode GskOffsetNode; + +struct _GskOffsetNode +{ + GskRenderNode render_node; + + GskRenderNode *child; + double x_offset; + double y_offset; +}; + +static void +gsk_offset_node_finalize (GskRenderNode *node) +{ + GskOffsetNode *self = (GskOffsetNode *) node; + + gsk_render_node_unref (self->child); +} + +static void +gsk_offset_node_draw (GskRenderNode *node, + cairo_t *cr) +{ + GskOffsetNode *self = (GskOffsetNode *) node; + + cairo_translate (cr, self->x_offset, self->y_offset); + gsk_render_node_draw (self->child, cr); +} + +#define GSK_OFFSET_NODE_VARIANT_TYPE "(dduv)" + +static GVariant * +gsk_offset_node_serialize (GskRenderNode *node) +{ + GskOffsetNode *self = (GskOffsetNode *) node; + + return g_variant_new (GSK_OFFSET_NODE_VARIANT_TYPE, + self->x_offset, + self->y_offset, + (guint32) gsk_render_node_get_node_type (self->child), + gsk_render_node_serialize_node (self->child)); +} + +static GskRenderNode * +gsk_offset_node_deserialize (GVariant *variant, + GError **error) +{ + double x_offset, y_offset; + guint32 child_type; + GVariant *child_variant; + GskRenderNode *result, *child; + + if (!check_variant_type (variant, GSK_OFFSET_NODE_VARIANT_TYPE, error)) + return NULL; + + g_variant_get (variant, GSK_OFFSET_NODE_VARIANT_TYPE, + &x_offset, &y_offset, + &child_type, &child_variant); + + child = gsk_render_node_deserialize_node (child_type, child_variant, error); + g_variant_unref (child_variant); + + if (child == NULL) + return NULL; + + result = gsk_offset_node_new (child, x_offset, y_offset); + + gsk_render_node_unref (child); + + return result; +} + +static const GskRenderNodeClass GSK_OFFSET_NODE_CLASS = { + GSK_OFFSET_NODE, + sizeof (GskOffsetNode), + "GskOffsetNode", + gsk_offset_node_finalize, + gsk_offset_node_draw, + gsk_offset_node_serialize, + gsk_offset_node_deserialize +}; + +/** + * gsk_offset_node_new: + * @child: The node to offset + * @x_offset: The x offset to apply + * @y_offset: The y offset to apply + * + * Creates a #GskRenderNode that will offset the given @child + * with the given @x_offset and @y_offset. + * + * This is a common special case of the matrix transform + * achieved by gsk_transform_node_new(). + * + * Returns: A new #GskRenderNode + */ +GskRenderNode * +gsk_offset_node_new (GskRenderNode *child, + double x_offset, + double y_offset) +{ + GskOffsetNode *self; + + g_return_val_if_fail (GSK_IS_RENDER_NODE (child), NULL); + + self = (GskOffsetNode *) gsk_render_node_new (&GSK_OFFSET_NODE_CLASS, 0); + + self->child = gsk_render_node_ref (child); + self->x_offset = x_offset; + self->y_offset = y_offset; + + graphene_rect_offset_r (&child->bounds, + x_offset, y_offset, + &self->render_node.bounds); + + return &self->render_node; +} + +/** + * gsk_offset_node_get_child: + * @node: a offset @GskRenderNode + * + * Gets the child node that is getting offset by the given @node. + * + * Returns: (transfer none): The child that is getting offset + **/ +GskRenderNode * +gsk_offset_node_get_child (GskRenderNode *node) +{ + GskOffsetNode *self = (GskOffsetNode *) node; + + g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_OFFSET_NODE), NULL); + + return self->child; +} + +double +gsk_offset_node_get_x_offset (GskRenderNode *node) +{ + GskOffsetNode *self = (GskOffsetNode *) node; + + g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_OFFSET_NODE), 0.0); + + return self->x_offset; +} + +double +gsk_offset_node_get_y_offset (GskRenderNode *node) +{ + GskOffsetNode *self = (GskOffsetNode *) node; + + g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_OFFSET_NODE), 0.0); + + return self->y_offset; +} + /*** GSK_OPACITY_NODE ***/ typedef struct _GskOpacityNode GskOpacityNode; diff --git a/gsk/vulkan/gskvulkanrenderpass.c b/gsk/vulkan/gskvulkanrenderpass.c index 1e7263757e..9bc38f3006 100644 --- a/gsk/vulkan/gskvulkanrenderpass.c +++ b/gsk/vulkan/gskvulkanrenderpass.c @@ -545,6 +545,7 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self, } return; + case GSK_OFFSET_NODE: case GSK_TRANSFORM_NODE: { graphene_matrix_t transform, mv; @@ -555,10 +556,23 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self, FALLBACK ("Transform nodes can't deal with clip type %u\n", clip->type); #endif - graphene_matrix_init_from_matrix (&transform, gsk_transform_node_peek_transform (node)); + if (gsk_render_node_get_node_type (node) == GSK_TRANSFORM_NODE) + { + child = gsk_transform_node_get_child (node); + graphene_matrix_init_from_matrix (&transform, gsk_transform_node_peek_transform (node)); + } + else + { + child = gsk_offset_node_get_child (node); + graphene_matrix_init_translate (&transform, + &GRAPHENE_POINT3D_INIT( + gsk_offset_node_get_x_offset (node), + gsk_offset_node_get_y_offset (node), + 0.0 + )); + } graphene_matrix_init_from_matrix (&mv, &self->mv); graphene_matrix_multiply (&transform, &mv, &self->mv); - child = gsk_transform_node_get_child (node); if (!gsk_vulkan_push_constants_transform (&op.constants.constants, constants, &transform, &child->bounds)) FALLBACK ("Transform nodes can't deal with clip type %u", constants->clip.type); op.type = GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS; diff --git a/gtk/inspector/gtktreemodelrendernode.c b/gtk/inspector/gtktreemodelrendernode.c index e8c16cadf3..9a52e1c9b2 100644 --- a/gtk/inspector/gtktreemodelrendernode.c +++ b/gtk/inspector/gtktreemodelrendernode.c @@ -534,6 +534,10 @@ append_node (GtkTreeModelRenderNode *nodemodel, /* no children */ break; + case GSK_OFFSET_NODE: + append_node (nodemodel, gsk_offset_node_get_child (node), priv->nodes->len - 1); + break; + case GSK_TRANSFORM_NODE: append_node (nodemodel, gsk_transform_node_get_child (node), priv->nodes->len - 1); break; diff --git a/gtk/inspector/recorder.c b/gtk/inspector/recorder.c index 8fae2630d0..c42acff512 100644 --- a/gtk/inspector/recorder.c +++ b/gtk/inspector/recorder.c @@ -171,6 +171,8 @@ node_type_name (GskRenderNodeType type) return "Outset Shadow"; case GSK_TRANSFORM_NODE: return "Transform"; + case GSK_OFFSET_NODE: + return "Offset"; case GSK_OPACITY_NODE: return "Opacity"; case GSK_COLOR_MATRIX_NODE: @@ -653,6 +655,11 @@ populate_render_node_properties (GtkListStore *store, } break; + case GSK_OFFSET_NODE: + add_float_row (store, "x offset", gsk_offset_node_get_x_offset (node)); + add_float_row (store, "y offset", gsk_offset_node_get_y_offset (node)); + break; + case GSK_NOT_A_RENDER_NODE: case GSK_TRANSFORM_NODE: default: