[gtk/mask-nodes: 4/5] wip: Do the same for stroke nodes
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/mask-nodes: 4/5] wip: Do the same for stroke nodes
- Date: Tue, 15 Dec 2020 03:24:37 +0000 (UTC)
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]