[gtk] rendernode: Add an offset node



commit ce743f28a19a1d33fee9311c131791c4bb332596
Author: Benjamin Otte <otte redhat com>
Date:   Tue Mar 20 02:46:57 2018 +0100

    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.

 gsk/gl/gskglrenderer.c                 |  27 ++++++
 gsk/gskbroadwayrenderer.c              |   1 +
 gsk/gskenums.h                         |   2 +
 gsk/gskrendernode.h                    |  11 +++
 gsk/gskrendernodeimpl.c                | 158 +++++++++++++++++++++++++++++++++
 gsk/vulkan/gskvulkanrenderpass.c       |  18 +++-
 gtk/inspector/gtktreemodelrendernode.c |   4 +
 gtk/inspector/recorder.c               |   7 ++
 8 files changed, 226 insertions(+), 2 deletions(-)
---
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:


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]