[mutter/gbsneto/effects-paint-nodes: 170/172] clutter/paint-nodes: Add new ClutterLayerNode API




commit d16539391ca546bb4a906e5fc45ffaa058e52447
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Mon Jun 29 15:17:27 2020 -0300

    clutter/paint-nodes: Add new ClutterLayerNode API
    
    ClutterLayerNode is the "offscreen framebuffer" node, that paints
    it's child nodes in a separate framebuffer, and then copies that
    framebuffer to the parent one.
    
    It'll be useful to hand ClutterLayerNode which texture to use, as
    this is a requirement for porting e.g. ClutterOffscreenEffect and
    subclasses.
    
    Add a new clutter_layer_node_new_with_texture() API.
    
    https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1340

 clutter/clutter/clutter-paint-nodes.c | 93 +++++++++++++++++++++++++++++++----
 clutter/clutter/clutter-paint-nodes.h |  4 ++
 2 files changed, 88 insertions(+), 9 deletions(-)
---
diff --git a/clutter/clutter/clutter-paint-nodes.c b/clutter/clutter/clutter-paint-nodes.c
index 2b5924858c..c3e6f94df6 100644
--- a/clutter/clutter/clutter-paint-nodes.c
+++ b/clutter/clutter/clutter-paint-nodes.c
@@ -1338,6 +1338,9 @@ struct _ClutterLayerNode
   CoglFramebuffer *offscreen;
 
   guint8 opacity;
+
+  gboolean projection_set : 1;
+  gboolean viewport_set : 1;
 };
 
 struct _ClutterLayerNodeClass
@@ -1370,19 +1373,38 @@ clutter_layer_node_pre_draw (ClutterPaintNode *node,
    */
   framebuffer = clutter_paint_context_get_framebuffer (paint_context);
   cogl_framebuffer_get_modelview_matrix (framebuffer, &matrix);
+  cogl_framebuffer_set_modelview_matrix (lnode->offscreen, &matrix);
 
-  clutter_paint_context_push_framebuffer (paint_context, lnode->offscreen);
+  if (lnode->viewport_set)
+    {
+      cogl_framebuffer_set_viewport (lnode->offscreen,
+                                     lnode->viewport.x,
+                                     lnode->viewport.y,
+                                     lnode->viewport.width,
+                                     lnode->viewport.height);
+    }
+  else
+    {
+      float viewport[4];
 
-  cogl_framebuffer_set_modelview_matrix (lnode->offscreen, &matrix);
+      cogl_framebuffer_get_viewport4fv (framebuffer, viewport);
+      cogl_framebuffer_set_viewport (lnode->offscreen,
+                                     viewport[0], viewport[1],
+                                     viewport[2], viewport[3]);
+    }
 
-  cogl_framebuffer_set_viewport (lnode->offscreen,
-                                 lnode->viewport.x,
-                                 lnode->viewport.y,
-                                 lnode->viewport.width,
-                                 lnode->viewport.height);
+  if (lnode->projection_set)
+    {
+      cogl_framebuffer_set_projection_matrix (lnode->offscreen,
+                                              &lnode->projection);
+    }
+  else
+    {
+      cogl_framebuffer_get_projection_matrix (framebuffer, &matrix);
+      cogl_framebuffer_set_projection_matrix (lnode->offscreen, &matrix);
+    }
 
-  cogl_framebuffer_set_projection_matrix (lnode->offscreen,
-                                          &lnode->projection);
+  clutter_paint_context_push_framebuffer (paint_context, lnode->offscreen);
 
   /* clear out the target framebuffer */
   cogl_framebuffer_clear4f (lnode->offscreen,
@@ -1521,7 +1543,9 @@ clutter_layer_node_new (const graphene_matrix_t *projection,
 
   res = _clutter_paint_node_create (CLUTTER_TYPE_LAYER_NODE);
 
+  res->projection_set = TRUE;
   res->projection = *projection;
+  res->viewport_set = TRUE;
   res->viewport = *viewport;
   res->fbo_width = width;
   res->fbo_height = height;
@@ -1561,3 +1585,54 @@ out:
 
   return (ClutterPaintNode *) res;
 }
+
+/**
+ * clutter_layer_node_new_with_texture:
+ * @texture: a #CoglTexture
+ * @opacity: the opacity to be used when drawing the layer
+ *
+ * Creates a new #ClutterLayerNode that will redirect drawing at
+ * @texture. The @texture will then be painted using the given
+ * @opacity.
+ *
+ * Return value: (transfer full): the newly created #ClutterLayerNode.
+ *   Use clutter_paint_node_unref() when done.
+ */
+ClutterPaintNode *
+clutter_layer_node_new_with_texture (CoglTexture *texture,
+                                     guint8       opacity)
+{
+  ClutterLayerNode *res;
+  CoglColor color;
+
+  res = _clutter_paint_node_create (CLUTTER_TYPE_LAYER_NODE);
+
+  res->projection_set = FALSE;
+  res->viewport_set = FALSE;
+  res->fbo_width = cogl_texture_get_width (texture);
+  res->fbo_height = cogl_texture_get_height (texture);
+  res->opacity = opacity;
+
+  res->offscreen = COGL_FRAMEBUFFER (cogl_offscreen_new_with_texture (texture));
+  if (res->offscreen == NULL)
+    {
+      g_critical ("%s: Unable to create an offscreen buffer", G_STRLOC);
+      goto out;
+    }
+
+  cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity);
+
+  /* the pipeline used to paint the texture; we use nearest
+   * interpolation filters because the texture is always
+   * going to be painted at a 1:1 texel:pixel ratio
+   */
+  res->pipeline = cogl_pipeline_copy (default_texture_pipeline);
+  cogl_pipeline_set_layer_filters (res->pipeline, 0,
+                                   COGL_PIPELINE_FILTER_NEAREST,
+                                   COGL_PIPELINE_FILTER_NEAREST);
+  cogl_pipeline_set_layer_texture (res->pipeline, 0, texture);
+  cogl_pipeline_set_color (res->pipeline, &color);
+
+out:
+  return (ClutterPaintNode *) res;
+}
diff --git a/clutter/clutter/clutter-paint-nodes.h b/clutter/clutter/clutter-paint-nodes.h
index 32b56a8d39..bac93752ef 100644
--- a/clutter/clutter/clutter-paint-nodes.h
+++ b/clutter/clutter/clutter-paint-nodes.h
@@ -209,6 +209,10 @@ ClutterPaintNode *      clutter_layer_node_new          (const graphene_matrix_t
                                                          float                    height,
                                                          guint8                   opacity);
 
+CLUTTER_EXPORT
+ClutterPaintNode * clutter_layer_node_new_with_texture (CoglTexture *texture,
+                                                        guint8       opacity);
+
 
 #define CLUTTER_TYPE_TRANSFORM_NODE             (clutter_transform_node_get_type ())
 #define CLUTTER_TRANSFORM_NODE(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
CLUTTER_TYPE_TRANSFORM_NODE, ClutterTransformNode))


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