[gtk/mask-nodes: 4/5] wip: Do the same for stroke nodes




commit 1abfb0458042c88934e6013af6684c5bac142345
Author: Matthias Clasen <mclasen redhat com>
Date:   Mon Dec 14 21:51:44 2020 -0500

    wip: Do the same for stroke nodes

 gsk/gl/gskglrenderer.c  | 70 +++++++++++++++++++++++++++++++++++++++++++++----
 gsk/gskrendernode.h     |  2 ++
 gsk/gskrendernodeimpl.c | 36 ++++++++++++++++++-------
 3 files changed, 94 insertions(+), 14 deletions(-)
---
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c
index 422d2e9c6d..25523578b5 100644
--- a/gsk/gl/gskglrenderer.c
+++ b/gsk/gl/gskglrenderer.c
@@ -2738,9 +2738,63 @@ render_fill_node (GskGLRenderer   *self,
                   RenderOpBuilder *builder)
 {
   GskRenderNode *child = gsk_fill_node_get_child (node);
+  TextureRegion child_region;
+  TextureRegion mask_region;
   GskRenderNode *mask_node;
+  gboolean is_offscreen1, is_offscreen2;
+  OpMask *op;
+
+  if (!add_offscreen_ops (self, builder,
+                          &node->bounds,
+                          child,
+                          &child_region, &is_offscreen1,
+                          FORCE_OFFSCREEN | RESET_CLIP))
+    {
+      gsk_gl_renderer_add_render_ops (self, child, builder);
+      return;
+    }
+
+  /* FIXME: figure out how to upload the texture without
+   * a temporary node. Using upload_texture doesn't work
+   * since the texture may end up in an atlas, giveing
+   * us incompatible texture coordinates. And forcing
+   * it to create a standalone texture ends up with
+   * flipped y :(
+   */
+  mask_node = gsk_texture_node_new (gsk_fill_node_get_mask (node), &node->bounds);
+
+  if (!add_offscreen_ops (self, builder,
+                          &node->bounds,
+                          mask_node,
+                          &mask_region, &is_offscreen2,
+                          FORCE_OFFSCREEN | RESET_CLIP))
+    {
+      gsk_render_node_unref (mask_node);
+      gsk_gl_renderer_add_render_ops (self, child, builder);
+      return;
+    }
+
+  gsk_render_node_unref (mask_node);
+
+  ops_set_program (builder, &self->programs->mask_program);
+
+  op = ops_begin (builder, OP_CHANGE_MASK);
+  op->mask = mask_region.texture_id;
+
+  ops_set_texture (builder, child_region.texture_id);
+
+  load_offscreen_vertex_data (ops_draw (builder, NULL), node, builder);
+}
+
+static inline void
+render_stroke_node (GskGLRenderer   *self,
+                    GskRenderNode   *node,
+                    RenderOpBuilder *builder)
+{
+  GskRenderNode *child = gsk_stroke_node_get_child (node);
   TextureRegion child_region;
   TextureRegion mask_region;
+  GskRenderNode *mask_node;
   gboolean is_offscreen1, is_offscreen2;
   OpMask *op;
 
@@ -2754,11 +2808,14 @@ render_fill_node (GskGLRenderer   *self,
       return;
     }
 
-  /* FIXME: Figure out how to make the texture coordinates set
-   * up properly without a temporary node
+  /* FIXME: figure out how to upload the texture without
+   * a temporary node. Using upload_texture doesn't work
+   * since the texture may end up in an atlas, giveing
+   * us incompatible texture coordinates. And forcing
+   * it to create a standalone texture ends up with
+   * flipped y :(
    */
-  mask_node = gsk_texture_node_new (gsk_fill_node_get_mask (node),
-                                    &node->bounds);
+  mask_node = gsk_texture_node_new (gsk_stroke_node_get_mask (node), &node->bounds);
 
   if (!add_offscreen_ops (self, builder,
                           &node->bounds,
@@ -3895,9 +3952,12 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer   *self,
       render_fill_node (self, node, builder);
     break;
 
+    case GSK_STROKE_NODE:
+      render_stroke_node (self, node, builder);
+    break;
+
     case GSK_REPEATING_LINEAR_GRADIENT_NODE:
     case GSK_REPEATING_RADIAL_GRADIENT_NODE:
-    case GSK_STROKE_NODE:
     case GSK_CAIRO_NODE:
     default:
       {
diff --git a/gsk/gskrendernode.h b/gsk/gskrendernode.h
index dd0e2ce1ee..a1628528c3 100644
--- a/gsk/gskrendernode.h
+++ b/gsk/gskrendernode.h
@@ -476,6 +476,8 @@ GDK_AVAILABLE_IN_ALL
 GskPath *               gsk_stroke_node_get_path                (GskRenderNode            *node);
 GDK_AVAILABLE_IN_ALL
 const GskStroke *       gsk_stroke_node_get_stroke              (GskRenderNode            *node);
+GDK_AVAILABLE_IN_ALL
+GdkTexture *            gsk_stroke_node_get_mask                (GskRenderNode            *node);
 
 GDK_AVAILABLE_IN_ALL
 GType                   gsk_shadow_node_get_type                (void) G_GNUC_CONST;
diff --git a/gsk/gskrendernodeimpl.c b/gsk/gskrendernodeimpl.c
index 99914e92e9..80d931701b 100644
--- a/gsk/gskrendernodeimpl.c
+++ b/gsk/gskrendernodeimpl.c
@@ -3743,10 +3743,10 @@ gsk_fill_node_diff (GskRenderNode  *node1,
 }
 
 static GdkTexture *
-make_path_mask (GskRenderNode *node)
+make_path_mask (graphene_rect_t *bounds,
+                GskPath         *path,
+                GskFillRule      fill_rule)
 {
-  GskFillNode *self = (GskFillNode *) node;
-  graphene_rect_t bounds;
   cairo_surface_t *surface;
   cairo_t *cr;
   int width;
@@ -3756,9 +3756,8 @@ make_path_mask (GskRenderNode *node)
   GBytes *bytes;
   GdkTexture *mask;
 
-  gsk_render_node_get_bounds (node, &bounds);
-  width = ceilf (bounds.size.width);
-  height = ceilf (bounds.size.height);
+  width = ceilf (bounds->size.width);
+  height = ceilf (bounds->size.height);
   stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, width);
 
   buffer = g_malloc0 (stride * height);
@@ -3768,8 +3767,9 @@ make_path_mask (GskRenderNode *node)
                                                  stride);
 
   cr = cairo_create (surface);
+  cairo_translate (cr, - bounds->origin.x, - bounds->origin.y);
 
-  switch (self->fill_rule)
+  switch (fill_rule)
   {
     case GSK_FILL_RULE_WINDING:
       cairo_set_fill_rule (cr, CAIRO_FILL_RULE_WINDING);
@@ -3782,7 +3782,7 @@ make_path_mask (GskRenderNode *node)
       break;
   }
 
-  gsk_path_to_cairo (self->path, cr);
+  gsk_path_to_cairo (path, cr);
   cairo_clip (cr);
 
   cairo_set_source_rgb (cr, 0, 0, 0);
@@ -3836,7 +3836,7 @@ gsk_fill_node_new (GskRenderNode *child,
   else
     graphene_rect_init_from_rect (&node->bounds, graphene_rect_zero ());
 
-  self->mask = make_path_mask (node);
+  self->mask = make_path_mask (&node->bounds, path, fill_rule);
 
   return node;
 }
@@ -3914,6 +3914,8 @@ struct _GskStrokeNode
 
   GskRenderNode *child;
   GskPath *path;
+  GskPath *stroke_path;
+  GdkTexture *mask;
   GskStroke stroke;
 };
 
@@ -3926,6 +3928,8 @@ gsk_stroke_node_finalize (GskRenderNode *node)
   gsk_render_node_unref (self->child);
   gsk_path_unref (self->path);
   gsk_stroke_clear (&self->stroke);
+  gsk_path_unref (self->stroke_path);
+  g_clear_object (&self->mask);
 
   parent_class->finalize (node);
 }
@@ -4007,9 +4011,13 @@ gsk_stroke_node_new (GskRenderNode   *child,
   self->path = gsk_path_ref (path);
   gsk_stroke_init_copy (&self->stroke, stroke);
 
+  self->stroke_path = gsk_path_stroke (self->path, &self->stroke);
+
   /* XXX: Figure out a way to compute bounds from the path */
   graphene_rect_init_from_rect (&node->bounds, &child->bounds);
 
+  self->mask = make_path_mask (&node->bounds, self->stroke_path, GSK_FILL_RULE_WINDING);
+
   return node;
 }
 
@@ -4068,6 +4076,16 @@ gsk_stroke_node_get_stroke (GskRenderNode *node)
   return &self->stroke;
 }
 
+GdkTexture *
+gsk_stroke_node_get_mask (GskRenderNode *node)
+{
+  GskStrokeNode *self = (GskStrokeNode *) node;
+
+  g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_STROKE_NODE), NULL);
+
+  return self->mask;
+}
+
 /*** GSK_SHADOW_NODE ***/
 
 /**


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