summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorges Basile Stavracas Neto <georges.stavracas@gmail.com>2020-12-09 14:49:02 -0300
committerGeorges Basile Stavracas Neto <georges.stavracas@gmail.com>2020-12-14 09:45:50 -0300
commit15f5087135d454b7115226b8d58344df1b0c0783 (patch)
tree093af9a6bf3ab9dedd60f688199febc70de2f0ca
parent3440fbd35883caae70529c1e1fa7d734287dba51 (diff)
downloadmutter-15f5087135d454b7115226b8d58344df1b0c0783.tar.gz
Introduce ClutterBlurNode
ClutterBlurNode is a paint node based on ClutterLayerNode that draws all children in an offscreen framebuffer, blurs this framebuffer, and finally paints the blurred contents according the the paint operations added. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1627>
-rw-r--r--clutter/clutter/clutter-paint-nodes.c148
-rw-r--r--clutter/clutter/clutter-paint-nodes.h21
2 files changed, 169 insertions, 0 deletions
diff --git a/clutter/clutter/clutter-paint-nodes.c b/clutter/clutter/clutter-paint-nodes.c
index ae0eac87e..37346d5c9 100644
--- a/clutter/clutter/clutter-paint-nodes.c
+++ b/clutter/clutter/clutter-paint-nodes.c
@@ -41,6 +41,7 @@
#include <cogl/cogl.h>
#include "clutter-actor-private.h"
+#include "clutter-blur-private.h"
#include "clutter-color.h"
#include "clutter-debug.h"
#include "clutter-private.h"
@@ -1808,3 +1809,150 @@ clutter_blit_node_add_blit_rectangle (ClutterBlitNode *blit_node,
dst_x + width,
dst_y + height);
}
+
+/*
+ * ClutterBlurNode
+ */
+
+struct _ClutterBlurNode
+{
+ ClutterLayerNode parent_instance;
+
+ ClutterBlur *blur;
+ unsigned int sigma;
+};
+
+G_DEFINE_TYPE (ClutterBlurNode, clutter_blur_node, CLUTTER_TYPE_LAYER_NODE)
+
+static void
+clutter_blur_node_post_draw (ClutterPaintNode *node,
+ ClutterPaintContext *paint_context)
+{
+ ClutterPaintNodeClass *parent_class =
+ CLUTTER_PAINT_NODE_CLASS (clutter_blur_node_parent_class);
+ ClutterBlurNode *blur_node = CLUTTER_BLUR_NODE (node);
+
+ clutter_blur_apply (blur_node->blur);
+
+ parent_class->post_draw (node, paint_context);
+}
+
+static void
+clutter_blur_node_finalize (ClutterPaintNode *node)
+{
+ ClutterBlurNode *blur_node = CLUTTER_BLUR_NODE (node);
+
+ g_clear_pointer (&blur_node->blur, clutter_blur_free);
+
+ CLUTTER_PAINT_NODE_CLASS (clutter_blur_node_parent_class)->finalize (node);
+}
+
+static JsonNode *
+clutter_blur_node_serialize (ClutterPaintNode *node)
+{
+ ClutterBlurNode *blur_node = CLUTTER_BLUR_NODE (node);
+ g_autoptr (JsonBuilder) builder = NULL;
+ g_autofree char *src_ptr = NULL;
+
+ src_ptr = g_strdup_printf ("%d", blur_node->sigma);
+
+ builder = json_builder_new ();
+ json_builder_begin_object (builder);
+ json_builder_set_member_name (builder, "sigma");
+ json_builder_add_string_value (builder, src_ptr);
+ json_builder_end_object (builder);
+
+ return json_builder_get_root (builder);
+}
+
+static void
+clutter_blur_node_class_init (ClutterBlurNodeClass *klass)
+{
+ ClutterPaintNodeClass *node_class;
+
+ node_class = CLUTTER_PAINT_NODE_CLASS (klass);
+ node_class->post_draw = clutter_blur_node_post_draw;
+ node_class->finalize = clutter_blur_node_finalize;
+ node_class->serialize = clutter_blur_node_serialize;
+}
+
+static void
+clutter_blur_node_init (ClutterBlurNode *blur_node)
+{
+}
+
+/**
+ * clutter_blur_node_new:
+ * @width width of the blur layer
+ * @height: height of the blur layer
+ * @sigma: sigma value of the blur
+ *
+ * Creates a new #ClutterBlurNode.
+ *
+ * Children of this node will be painted inside a separate framebuffer,
+ * which will be blurred and painted on the current draw framebuffer.
+ *
+ * Return value: (transfer full): the newly created #ClutterBlurNode.
+ * Use clutter_paint_node_unref() when done.
+ */
+ClutterPaintNode *
+clutter_blur_node_new (unsigned int width,
+ unsigned int height,
+ unsigned int sigma)
+{
+ g_autoptr (CoglOffscreen) offscreen = NULL;
+ g_autoptr (GError) error = NULL;
+ graphene_matrix_t projection;
+ ClutterLayerNode *layer_node;
+ ClutterBlurNode *blur_node;
+ CoglTexture2D *tex_2d;
+ CoglContext *context;
+ CoglTexture *texture;
+ ClutterBlur *blur;
+
+ blur_node = _clutter_paint_node_create (CLUTTER_TYPE_BLUR_NODE);
+ blur_node->sigma = sigma;
+ context = clutter_backend_get_cogl_context (clutter_get_default_backend ());
+ tex_2d = cogl_texture_2d_new_with_size (context, width, height);
+
+ texture = COGL_TEXTURE (tex_2d);
+ cogl_texture_set_premultiplied (texture, TRUE);
+
+ offscreen = cogl_offscreen_new_with_texture (texture);
+ cogl_object_unref (tex_2d);
+ if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (offscreen), &error))
+ {
+ g_warning ("Unable to allocate paint node offscreen: %s",
+ error->message);
+ goto out;
+ }
+
+ blur = clutter_blur_new (texture, sigma);
+ blur_node->blur = blur;
+
+ if (!blur)
+ {
+ g_warning ("Failed to create blur pipeline");
+ goto out;
+ }
+
+ layer_node = CLUTTER_LAYER_NODE (blur_node);
+ layer_node->offscreen = COGL_FRAMEBUFFER (g_steal_pointer (&offscreen));
+ layer_node->pipeline = cogl_pipeline_copy (default_texture_pipeline);
+ cogl_pipeline_set_layer_filters (layer_node->pipeline, 0,
+ COGL_PIPELINE_FILTER_LINEAR,
+ COGL_PIPELINE_FILTER_LINEAR);
+ cogl_pipeline_set_layer_texture (layer_node->pipeline,
+ 0,
+ clutter_blur_get_texture (blur));
+
+ graphene_matrix_init_translate (&projection,
+ &GRAPHENE_POINT3D_INIT (-(width / 2.f),
+ -(height / 2.f),
+ 0.f));
+ graphene_matrix_scale (&projection, 2.f / width, -2.f / height, 1.f);
+ cogl_framebuffer_set_projection_matrix (layer_node->offscreen, &projection);
+
+out:
+ return (ClutterPaintNode *) blur_node;
+}
diff --git a/clutter/clutter/clutter-paint-nodes.h b/clutter/clutter/clutter-paint-nodes.h
index 410bebc88..8c01dd7d2 100644
--- a/clutter/clutter/clutter-paint-nodes.h
+++ b/clutter/clutter/clutter-paint-nodes.h
@@ -263,6 +263,27 @@ void clutter_blit_node_add_blit_rectangle (ClutterBlitNode *blit_node,
int width,
int height);
+#define CLUTTER_TYPE_BLUR_NODE (clutter_blur_node_get_type ())
+#define CLUTTER_BLUR_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BLUR_NODE, ClutterBlurNode))
+#define CLUTTER_IS_BLUR_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BLUR_NODE))
+
+/**
+ * ClutterBlurNode:
+ *
+ * The #ClutterBurNode structure is an opaque
+ * type whose members cannot be directly accessed.
+ */
+typedef struct _ClutterBlurNode ClutterBlurNode;
+typedef struct _ClutterLayerNodeClass ClutterBlurNodeClass;
+
+CLUTTER_EXPORT
+GType clutter_blur_node_get_type (void) G_GNUC_CONST;
+
+CLUTTER_EXPORT
+ClutterPaintNode * clutter_blur_node_new (unsigned int width,
+ unsigned int height,
+ unsigned int sigma);
+
G_END_DECLS
#endif /* __CLUTTER_PAINT_NODES_H__ */