[mutter] Introduce ClutterBlurNode



commit 15f5087135d454b7115226b8d58344df1b0c0783
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Wed Dec 9 14:49:02 2020 -0300

    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>

 clutter/clutter/clutter-paint-nodes.c | 148 ++++++++++++++++++++++++++++++++++
 clutter/clutter/clutter-paint-nodes.h |  21 +++++
 2 files changed, 169 insertions(+)
---
diff --git a/clutter/clutter/clutter-paint-nodes.c b/clutter/clutter/clutter-paint-nodes.c
index ae0eac87ec..37346d5c90 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 410bebc889..8c01dd7d25 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__ */


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