[gtk/mask-nodes: 120/123] gsk: Introduce mask nodes
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/mask-nodes: 120/123] gsk: Introduce mask nodes
- Date: Mon, 21 Dec 2020 02:57:31 +0000 (UTC)
commit ac17cb5549ba778bb9a39ba9b8a2186b3d670256
Author: Matthias Clasen <mclasen redhat com>
Date: Wed Mar 28 19:06:39 2018 +0200
gsk: Introduce mask nodes
Add GskMaskNode, and support it in the render node
parser, in the inspector and in GtkSnapshot.
The rendering is just fallback for now.
Based on old work by Timm Bäder.
gsk/gl/gskglrenderer.c | 1 +
gsk/gskenums.h | 3 +-
gsk/gskrendernode.h | 12 +++++
gsk/gskrendernodeimpl.c | 94 ++++++++++++++++++++++++++++++++++++++++
gsk/gskrendernodeparser.c | 37 ++++++++++++++++
gsk/gskrendernodeprivate.h | 2 +-
gsk/vulkan/gskvulkanrenderpass.c | 1 +
gtk/gtksnapshot.c | 70 ++++++++++++++++++++++++++++++
gtk/gtksnapshot.h | 2 +
gtk/inspector/recorder.c | 8 ++++
10 files changed, 228 insertions(+), 2 deletions(-)
---
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c
index 44ba02dfe0..1317893f8b 100644
--- a/gsk/gl/gskglrenderer.c
+++ b/gsk/gl/gskglrenderer.c
@@ -3810,6 +3810,7 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
case GSK_FILL_NODE:
case GSK_STROKE_NODE:
case GSK_CAIRO_NODE:
+ case GSK_MASK_NODE:
default:
{
render_fallback_node (self, node, builder);
diff --git a/gsk/gskenums.h b/gsk/gskenums.h
index 405c845eba..3e9df5a0fc 100644
--- a/gsk/gskenums.h
+++ b/gsk/gskenums.h
@@ -81,7 +81,8 @@ typedef enum {
GSK_TEXT_NODE,
GSK_BLUR_NODE,
GSK_DEBUG_NODE,
- GSK_GL_SHADER_NODE
+ GSK_GL_SHADER_NODE,
+ GSK_MASK_NODE,
} GskRenderNodeType;
/**
diff --git a/gsk/gskrendernode.h b/gsk/gskrendernode.h
index 4b842a2db8..0e0e893e12 100644
--- a/gsk/gskrendernode.h
+++ b/gsk/gskrendernode.h
@@ -166,6 +166,7 @@ GskRenderNode * gsk_render_node_deserialize (GBytes
#define GSK_TYPE_TEXT_NODE (gsk_text_node_get_type())
#define GSK_TYPE_BLUR_NODE (gsk_blur_node_get_type())
#define GSK_TYPE_GL_SHADER_NODE (gsk_gl_shader_node_get_type())
+#define GSK_TYPE_MASK_NODE (gsk_mask_node_get_type())
typedef struct _GskDebugNode GskDebugNode;
typedef struct _GskColorNode GskColorNode;
@@ -194,6 +195,7 @@ typedef struct _GskCrossFadeNode GskCrossFadeNode;
typedef struct _GskTextNode GskTextNode;
typedef struct _GskBlurNode GskBlurNode;
typedef struct _GskGLShaderNode GskGLShaderNode;
+typedef struct _GskMaskNode GskMaskNode;
GDK_AVAILABLE_IN_ALL
GType gsk_debug_node_get_type (void) G_GNUC_CONST;
@@ -561,6 +563,16 @@ GBytes * gsk_gl_shader_node_get_args (GskRenderNode
GDK_AVAILABLE_IN_ALL
GskGLShader * gsk_gl_shader_node_get_shader (GskRenderNode *node);
+GDK_AVAILABLE_IN_ALL
+GType gsk_mask_node_get_type (void) G_GNUC_CONST;
+GDK_AVAILABLE_IN_ALL
+GskRenderNode * gsk_mask_node_new (GskRenderNode *source_child,
+ GskRenderNode *mask_child);
+GDK_AVAILABLE_IN_ALL
+GskRenderNode * gsk_mask_node_get_source (GskRenderNode *node);
+GDK_AVAILABLE_IN_ALL
+GskRenderNode * gsk_mask_node_get_mask (GskRenderNode *node);
+
G_END_DECLS
#endif /* __GSK_RENDER_NODE_H__ */
diff --git a/gsk/gskrendernodeimpl.c b/gsk/gskrendernodeimpl.c
index 836a28b856..00be90e072 100644
--- a/gsk/gskrendernodeimpl.c
+++ b/gsk/gskrendernodeimpl.c
@@ -5520,6 +5520,83 @@ gsk_gl_shader_node_get_args (GskRenderNode *node)
return self->args;
}
+/*** GSK_MASK_NODE ***/
+
+typedef struct _GskMaskNode GskMaskNode;
+
+struct _GskMaskNode
+{
+ GskRenderNode render_node;
+
+ GskRenderNode *mask_child;
+ GskRenderNode *source_child;
+};
+
+static void
+gsk_mask_node_finalize (GskRenderNode *node)
+{
+ GskMaskNode *self = (GskMaskNode *) node;
+
+ gsk_render_node_unref (self->source_child);
+ gsk_render_node_unref (self->mask_child);
+}
+
+static void
+gsk_mask_node_draw (GskRenderNode *node,
+ cairo_t *cr)
+{
+ GskMaskNode *self = (GskMaskNode *) node;
+ cairo_pattern_t *mask_pattern;
+
+ cairo_push_group (cr);
+ gsk_render_node_draw (self->source_child, cr);
+ cairo_pop_group_to_source (cr);
+
+ cairo_push_group (cr);
+ gsk_render_node_draw (self->mask_child, cr);
+ mask_pattern = cairo_pop_group (cr);
+
+ cairo_mask (cr, mask_pattern);
+}
+
+GskRenderNode *
+gsk_mask_node_new (GskRenderNode *source_child,
+ GskRenderNode *mask_child)
+{
+ GskMaskNode *self;
+
+ g_return_val_if_fail (GSK_IS_RENDER_NODE (source_child), NULL);
+ g_return_val_if_fail (GSK_IS_RENDER_NODE (mask_child), NULL);
+
+ self = gsk_render_node_alloc (GSK_MASK_NODE);
+ self->source_child = gsk_render_node_ref (source_child);
+ self->mask_child = gsk_render_node_ref (mask_child);
+
+ graphene_rect_union (&source_child->bounds, &mask_child->bounds, &self->render_node.bounds);
+
+ return &self->render_node;
+}
+
+GskRenderNode *
+gsk_mask_node_get_source (GskRenderNode *node)
+{
+ GskMaskNode *self = (GskMaskNode *) node;
+
+ g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_MASK_NODE), NULL);
+
+ return self->source_child;
+}
+
+GskRenderNode *
+gsk_mask_node_get_mask (GskRenderNode *node)
+{
+ GskMaskNode *self = (GskMaskNode *) node;
+
+ g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_MASK_NODE), NULL);
+
+ return self->mask_child;
+}
+
GType gsk_render_node_types[GSK_RENDER_NODE_TYPE_N_TYPES];
#ifndef I_
@@ -5561,6 +5638,7 @@ GSK_DEFINE_RENDER_NODE_TYPE (gsk_text_node, GSK_TEXT_NODE)
GSK_DEFINE_RENDER_NODE_TYPE (gsk_blur_node, GSK_BLUR_NODE)
GSK_DEFINE_RENDER_NODE_TYPE (gsk_gl_shader_node, GSK_GL_SHADER_NODE)
GSK_DEFINE_RENDER_NODE_TYPE (gsk_debug_node, GSK_DEBUG_NODE)
+GSK_DEFINE_RENDER_NODE_TYPE (gsk_mask_node, GSK_MASK_NODE)
static void
gsk_render_node_init_types_once (void)
@@ -5996,6 +6074,22 @@ gsk_render_node_init_types_once (void)
GType node_type = gsk_render_node_type_register_static (I_("GskDebugNode"), &node_info);
gsk_render_node_types[GSK_DEBUG_NODE] = node_type;
}
+
+ {
+ const GskRenderNodeTypeInfo node_info =
+ {
+ GSK_MASK_NODE,
+ sizeof (GskMaskNode),
+ NULL,
+ gsk_mask_node_finalize,
+ gsk_mask_node_draw,
+ NULL,
+ NULL,
+ };
+
+ GType node_type = gsk_render_node_type_register_static (I_("GskMaskNode"), &node_info);
+ gsk_render_node_types[GSK_MASK_NODE] = node_type;
+ }
}
/*< private >
* gsk_render_node_init_types:
diff --git a/gsk/gskrendernodeparser.c b/gsk/gskrendernodeparser.c
index 12404094f3..2bb85f9875 100644
--- a/gsk/gskrendernodeparser.c
+++ b/gsk/gskrendernodeparser.c
@@ -1592,6 +1592,31 @@ parse_blend_node (GtkCssParser *parser)
return result;
}
+static GskRenderNode *
+parse_mask_node (GtkCssParser *parser)
+{
+ GskRenderNode *source = NULL;
+ GskRenderNode *mask = NULL;
+ const Declaration declarations[] = {
+ { "source", parse_node, clear_node, &source },
+ { "mask", parse_node, clear_node, &mask },
+ };
+ GskRenderNode *result;
+
+ parse_declarations (parser, declarations, G_N_ELEMENTS(declarations));
+ if (source == NULL)
+ source = create_default_render_node ();
+ if (mask == NULL)
+ mask = gsk_color_node_new (&GDK_RGBA("AAFF00"), &GRAPHENE_RECT_INIT (0, 0, 50, 50));
+
+ result = gsk_mask_node_new (source, mask);
+
+ gsk_render_node_unref (source);
+ gsk_render_node_unref (mask);
+
+ return result;
+}
+
static GskRenderNode *
parse_repeat_node (GtkCssParser *parser)
{
@@ -2074,6 +2099,7 @@ parse_node (GtkCssParser *parser,
{ "texture", parse_texture_node },
{ "transform", parse_transform_node },
{ "glshader", parse_glshader_node },
+ { "mask", parse_mask_node },
};
GskRenderNode **node_p = out_node;
guint i;
@@ -3258,6 +3284,17 @@ render_node_print (Printer *p,
}
break;
+ case GSK_MASK_NODE:
+ {
+ start_node (p, "mask");
+
+ append_node_param (p, "source", gsk_mask_node_get_source (node));
+ append_node_param (p, "mask", gsk_mask_node_get_mask (node));
+
+ end_node (p);
+ }
+ break;
+
case GSK_NOT_A_RENDER_NODE:
g_assert_not_reached ();
break;
diff --git a/gsk/gskrendernodeprivate.h b/gsk/gskrendernodeprivate.h
index 7e11a14b8f..89da9a1649 100644
--- a/gsk/gskrendernodeprivate.h
+++ b/gsk/gskrendernodeprivate.h
@@ -13,7 +13,7 @@ typedef struct _GskRenderNodeClass GskRenderNodeClass;
* We don't add an "n-types" value to avoid having to handle
* it in every single switch.
*/
-#define GSK_RENDER_NODE_TYPE_N_TYPES (GSK_GL_SHADER_NODE + 1)
+#define GSK_RENDER_NODE_TYPE_N_TYPES (GSK_MASK_NODE + 1)
extern GType gsk_render_node_types[];
diff --git a/gsk/vulkan/gskvulkanrenderpass.c b/gsk/vulkan/gskvulkanrenderpass.c
index d403c0c5b6..78b62c0b6c 100644
--- a/gsk/vulkan/gskvulkanrenderpass.c
+++ b/gsk/vulkan/gskvulkanrenderpass.c
@@ -262,6 +262,7 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self,
case GSK_CONIC_GRADIENT_NODE:
case GSK_FILL_NODE:
case GSK_STROKE_NODE:
+ case GSK_MASK_NODE:
default:
FALLBACK ("Unsupported node '%s'", g_type_name_from_instance ((GTypeInstance *) node));
diff --git a/gtk/gtksnapshot.c b/gtk/gtksnapshot.c
index 8e6d647348..b498a95181 100644
--- a/gtk/gtksnapshot.c
+++ b/gtk/gtksnapshot.c
@@ -133,6 +133,9 @@ struct _GtkSnapshotState {
struct {
char *message;
} debug;
+ struct {
+ GskRenderNode *source_node;
+ } mask;
} data;
};
@@ -1389,6 +1392,73 @@ gtk_snapshot_push_blend (GtkSnapshot *snapshot,
NULL);
}
+static GskRenderNode *
+gtk_snapshot_collect_mask_mask (GtkSnapshot *snapshot,
+ GtkSnapshotState *state,
+ GskRenderNode **nodes,
+ guint n_nodes)
+{
+ GskRenderNode *source_child, *mask_child, *mask_node;
+
+ mask_child = gtk_snapshot_collect_default (snapshot, state, nodes, n_nodes);
+ source_child = state->data.mask.source_node;
+
+ if (source_child == NULL ||
+ mask_child == NULL)
+ return NULL;
+
+ mask_node = gsk_mask_node_new (source_child, mask_child);
+
+ gsk_render_node_unref (source_child);
+ gsk_render_node_unref (mask_child);
+
+ return mask_node;
+}
+
+static GskRenderNode *
+gtk_snapshot_collect_mask_source (GtkSnapshot *snapshot,
+ GtkSnapshotState *state,
+ GskRenderNode **nodes,
+ guint n_nodes)
+{
+ GtkSnapshotState *prev_state = gtk_snapshot_get_previous_state (snapshot);
+
+ g_assert (prev_state->collect_func == gtk_snapshot_collect_mask_mask);
+
+ prev_state->data.mask.source_node = gtk_snapshot_collect_default (snapshot, state, nodes, n_nodes);
+
+ return NULL;
+}
+
+static void
+gtk_snapshot_clear_mask_source (GtkSnapshotState *state)
+{
+ g_clear_pointer (&(state->data.mask.source_node), gsk_render_node_unref);
+}
+
+/**
+ * gtk_snapshot_push_mask:
+ * @snapshot: a #GtkSnapshot
+ *
+ * Calling this function requires 2 subsequent calls to gtk_snapshot_pop().
+ **/
+void
+gtk_snapshot_push_mask (GtkSnapshot *snapshot)
+{
+ GtkSnapshotState *current_state = gtk_snapshot_get_current_state (snapshot);
+ GtkSnapshotState *source_state;
+
+ source_state = gtk_snapshot_push_state (snapshot,
+ current_state->transform,
+ gtk_snapshot_collect_mask_source,
+ gtk_snapshot_clear_mask_source);
+
+ gtk_snapshot_push_state (snapshot,
+ source_state->transform,
+ gtk_snapshot_collect_mask_mask,
+ NULL);
+}
+
static GskRenderNode *
gtk_snapshot_collect_cross_fade_end (GtkSnapshot *snapshot,
GtkSnapshotState *state,
diff --git a/gtk/gtksnapshot.h b/gtk/gtksnapshot.h
index 3244f5b0d3..4aba94969a 100644
--- a/gtk/gtksnapshot.h
+++ b/gtk/gtksnapshot.h
@@ -104,6 +104,8 @@ GDK_AVAILABLE_IN_ALL
void gtk_snapshot_push_blend (GtkSnapshot *snapshot,
GskBlendMode blend_mode);
GDK_AVAILABLE_IN_ALL
+void gtk_snapshot_push_mask (GtkSnapshot *snapshot);
+GDK_AVAILABLE_IN_ALL
void gtk_snapshot_push_cross_fade (GtkSnapshot *snapshot,
double progress);
GDK_AVAILABLE_IN_ALL
diff --git a/gtk/inspector/recorder.c b/gtk/inspector/recorder.c
index 7fcb6e9849..1959681304 100644
--- a/gtk/inspector/recorder.c
+++ b/gtk/inspector/recorder.c
@@ -174,6 +174,10 @@ create_list_model_for_render_node (GskRenderNode *node)
return create_render_node_list_model ((GskRenderNode *[2]) { gsk_blend_node_get_bottom_child (node),
gsk_blend_node_get_top_child (node) }, 2);
+ case GSK_MASK_NODE:
+ return create_render_node_list_model ((GskRenderNode *[2]) { gsk_mask_node_get_source (node),
+ gsk_mask_node_get_mask (node) }, 2);
+
case GSK_CROSS_FADE_NODE:
return create_render_node_list_model ((GskRenderNode *[2]) { gsk_cross_fade_node_get_start_child
(node),
gsk_cross_fade_node_get_end_child (node)
}, 2);
@@ -304,6 +308,8 @@ node_type_name (GskRenderNodeType type)
return "Blur";
case GSK_GL_SHADER_NODE:
return "GL Shader";
+ case GSK_MASK_NODE:
+ return "Mask";
}
}
@@ -335,6 +341,7 @@ node_name (GskRenderNode *node)
case GSK_STROKE_NODE:
case GSK_SHADOW_NODE:
case GSK_BLEND_NODE:
+ case GSK_MASK_NODE:
case GSK_CROSS_FADE_NODE:
case GSK_TEXT_NODE:
case GSK_BLUR_NODE:
@@ -1193,6 +1200,7 @@ populate_render_node_properties (GtkListStore *store,
break;
case GSK_NOT_A_RENDER_NODE:
+ case GSK_MASK_NODE:
default:
break;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]