[gtk/mask-nodes: 5/5] Move the mask creation to the renderer




commit ed9e2a7e74d8bf8e1874914ee372b0ab064efd90
Author: Matthias Clasen <mclasen redhat com>
Date:   Mon Dec 14 22:22:34 2020 -0500

    Move the mask creation to the renderer
    
    This should not live in the render nodes.
    Caching will need to happen in the renderer,
    similar to how we're caching glyphs and icons.

 gsk/gl/gskglrenderer.c  | 80 +++++++++++++++++++++++++++++++++++++++++--
 gsk/gskrendernode.h     |  4 ---
 gsk/gskrendernodeimpl.c | 91 -------------------------------------------------
 3 files changed, 78 insertions(+), 97 deletions(-)
---
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c
index 25523578b5..c5c0d5c9c1 100644
--- a/gsk/gl/gskglrenderer.c
+++ b/gsk/gl/gskglrenderer.c
@@ -2732,6 +2732,63 @@ render_mask_node (GskGLRenderer   *self,
   load_offscreen_vertex_data (ops_draw (builder, NULL), node, builder);
 }
 
+static GdkTexture *
+make_path_mask (graphene_rect_t *bounds,
+                GskPath         *path,
+                GskFillRule      fill_rule)
+{
+  cairo_surface_t *surface;
+  cairo_t *cr;
+  int width;
+  int height;
+  int stride;
+  guchar *buffer;
+  GBytes *bytes;
+  GdkTexture *mask;
+
+  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);
+  surface = cairo_image_surface_create_for_data (buffer,
+                                                 CAIRO_FORMAT_ARGB32,
+                                                 width, height,
+                                                 stride);
+
+  cr = cairo_create (surface);
+  cairo_translate (cr, - bounds->origin.x, - bounds->origin.y);
+
+ switch (fill_rule)
+  {
+    case GSK_FILL_RULE_WINDING:
+      cairo_set_fill_rule (cr, CAIRO_FILL_RULE_WINDING);
+      break;
+    case GSK_FILL_RULE_EVEN_ODD:
+      cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
+      break;
+    default:
+      g_assert_not_reached ();
+      break;
+  }
+
+  gsk_path_to_cairo (path, cr);
+  cairo_clip (cr);
+
+  cairo_set_source_rgb (cr, 0, 0, 0);
+  cairo_paint (cr);
+
+  cairo_destroy (cr);
+
+  bytes = g_bytes_new_take (buffer, stride * height);
+  mask = gdk_memory_texture_new (width, height, GDK_MEMORY_DEFAULT, bytes, stride);
+  g_bytes_unref (bytes);
+
+  cairo_surface_destroy (surface);
+
+  return mask;
+}
+
 static inline void
 render_fill_node (GskGLRenderer   *self,
                   GskRenderNode   *node,
@@ -2740,6 +2797,7 @@ render_fill_node (GskGLRenderer   *self,
   GskRenderNode *child = gsk_fill_node_get_child (node);
   TextureRegion child_region;
   TextureRegion mask_region;
+  GdkTexture *mask;
   GskRenderNode *mask_node;
   gboolean is_offscreen1, is_offscreen2;
   OpMask *op;
@@ -2754,6 +2812,11 @@ render_fill_node (GskGLRenderer   *self,
       return;
     }
 
+  /* TODO: cache masks */
+  mask = make_path_mask (&node->bounds,
+                         gsk_fill_node_get_path (node),
+                         gsk_fill_node_get_fill_rule (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
@@ -2761,7 +2824,7 @@ render_fill_node (GskGLRenderer   *self,
    * 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 (mask, &node->bounds);
 
   if (!add_offscreen_ops (self, builder,
                           &node->bounds,
@@ -2770,11 +2833,13 @@ render_fill_node (GskGLRenderer   *self,
                           FORCE_OFFSCREEN | RESET_CLIP))
     {
       gsk_render_node_unref (mask_node);
+      g_object_unref (mask);
       gsk_gl_renderer_add_render_ops (self, child, builder);
       return;
     }
 
   gsk_render_node_unref (mask_node);
+  g_object_unref (mask);
 
   ops_set_program (builder, &self->programs->mask_program);
 
@@ -2793,6 +2858,8 @@ render_stroke_node (GskGLRenderer   *self,
 {
   GskRenderNode *child = gsk_stroke_node_get_child (node);
   TextureRegion child_region;
+  GskPath *path;
+  GdkTexture *mask;
   TextureRegion mask_region;
   GskRenderNode *mask_node;
   gboolean is_offscreen1, is_offscreen2;
@@ -2808,6 +2875,11 @@ render_stroke_node (GskGLRenderer   *self,
       return;
     }
 
+  /* TODO: cache masks */
+  path = gsk_path_stroke (gsk_stroke_node_get_path (node),
+                          (GskStroke *)gsk_stroke_node_get_stroke (node));
+  mask = make_path_mask (&node->bounds, path, GSK_FILL_RULE_WINDING);
+
   /* 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
@@ -2815,7 +2887,7 @@ render_stroke_node (GskGLRenderer   *self,
    * it to create a standalone texture ends up with
    * flipped y :(
    */
-  mask_node = gsk_texture_node_new (gsk_stroke_node_get_mask (node), &node->bounds);
+  mask_node = gsk_texture_node_new (mask, &node->bounds);
 
   if (!add_offscreen_ops (self, builder,
                           &node->bounds,
@@ -2824,11 +2896,15 @@ render_stroke_node (GskGLRenderer   *self,
                           FORCE_OFFSCREEN | RESET_CLIP))
     {
       gsk_render_node_unref (mask_node);
+      g_object_unref (mask);
+      gsk_path_unref (path);
       gsk_gl_renderer_add_render_ops (self, child, builder);
       return;
     }
 
   gsk_render_node_unref (mask_node);
+  g_object_unref (mask);
+  gsk_path_unref (path);
 
   ops_set_program (builder, &self->programs->mask_program);
 
diff --git a/gsk/gskrendernode.h b/gsk/gskrendernode.h
index a1628528c3..0e0e893e12 100644
--- a/gsk/gskrendernode.h
+++ b/gsk/gskrendernode.h
@@ -461,8 +461,6 @@ GDK_AVAILABLE_IN_ALL
 GskPath *               gsk_fill_node_get_path                  (GskRenderNode            *node);
 GDK_AVAILABLE_IN_ALL
 GskFillRule             gsk_fill_node_get_fill_rule             (GskRenderNode            *node);
-GDK_AVAILABLE_IN_ALL
-GdkTexture *            gsk_fill_node_get_mask                  (GskRenderNode            *node);
 
 GDK_AVAILABLE_IN_ALL
 GType                   gsk_stroke_node_get_type                (void) G_GNUC_CONST;
@@ -476,8 +474,6 @@ 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 80d931701b..92b5a85ed1 100644
--- a/gsk/gskrendernodeimpl.c
+++ b/gsk/gskrendernodeimpl.c
@@ -3670,7 +3670,6 @@ struct _GskFillNode
   GskRenderNode *child;
   GskPath *path;
   GskFillRule fill_rule;
-  GdkTexture *mask;
 };
 
 static void
@@ -3681,7 +3680,6 @@ gsk_fill_node_finalize (GskRenderNode *node)
 
   gsk_render_node_unref (self->child);
   gsk_path_unref (self->path);
-  g_clear_object (&self->mask);
 
   parent_class->finalize (node);
 }
@@ -3742,65 +3740,6 @@ gsk_fill_node_diff (GskRenderNode  *node1,
     }
 }
 
-static GdkTexture *
-make_path_mask (graphene_rect_t *bounds,
-                GskPath         *path,
-                GskFillRule      fill_rule)
-{
-  cairo_surface_t *surface;
-  cairo_t *cr;
-  int width;
-  int height;
-  int stride;
-  guchar *buffer;
-  GBytes *bytes;
-  GdkTexture *mask;
-
-  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);
-  surface = cairo_image_surface_create_for_data (buffer,
-                                                 CAIRO_FORMAT_ARGB32,
-                                                 width, height,
-                                                 stride);
-
-  cr = cairo_create (surface);
-  cairo_translate (cr, - bounds->origin.x, - bounds->origin.y);
-
-  switch (fill_rule)
-  {
-    case GSK_FILL_RULE_WINDING:
-      cairo_set_fill_rule (cr, CAIRO_FILL_RULE_WINDING);
-      break;
-    case GSK_FILL_RULE_EVEN_ODD:
-      cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
-      break;
-    default:
-      g_assert_not_reached ();
-      break;
-  }
-
-  gsk_path_to_cairo (path, cr);
-  cairo_clip (cr);
-
-  cairo_set_source_rgb (cr, 0, 0, 0);
-  cairo_paint (cr);
-
-  cairo_destroy (cr);
-
-  bytes = g_bytes_new_take (buffer, stride * height);
-  mask = gdk_memory_texture_new (width, height, GDK_MEMORY_DEFAULT, bytes, stride);
-  g_bytes_unref (bytes);
-
-  gdk_texture_save_to_png (mask, "mask.png");
-
-  cairo_surface_destroy (surface);
-
-  return mask;
-}
-
 /**
  * gsk_fill_node_new:
  * @child: The node to fill the area with
@@ -3836,8 +3775,6 @@ gsk_fill_node_new (GskRenderNode *child,
   else
     graphene_rect_init_from_rect (&node->bounds, graphene_rect_zero ());
 
-  self->mask = make_path_mask (&node->bounds, path, fill_rule);
-
   return node;
 }
 
@@ -3896,16 +3833,6 @@ gsk_fill_node_get_fill_rule (GskRenderNode *node)
   return self->fill_rule;
 }
 
-GdkTexture *
-gsk_fill_node_get_mask (GskRenderNode *node)
-{
-  GskFillNode *self = (GskFillNode *) node;
-
-  g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_FILL_NODE), NULL);
-
-  return self->mask;
-}
-
 /*** GSK_STROKE_NODE ***/
 
 struct _GskStrokeNode
@@ -3914,8 +3841,6 @@ struct _GskStrokeNode
 
   GskRenderNode *child;
   GskPath *path;
-  GskPath *stroke_path;
-  GdkTexture *mask;
   GskStroke stroke;
 };
 
@@ -3928,8 +3853,6 @@ 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);
 }
@@ -4011,13 +3934,9 @@ 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;
 }
 
@@ -4076,16 +3995,6 @@ 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]