[mutter] clutter/paint-node: Add multi-rect operations



commit 2f01ef69e31d5434d2f6f57453f548e208e90606
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Mon Dec 14 14:28:42 2020 -0300

    clutter/paint-node: Add multi-rect operations
    
    Add a new pair of APIs corresponding to CoglFramebuffer's draw_rectangles()
    and draw_textured_rectangles(). They're generally more performance compared
    to adding multiple single-rect operations. These variants are heavily used
    by GNOME Shell's CSS implementation.
    
    The op array is built to match cogl_framebuffer_draw_textured_rectangles()
    always, which means it's a series of 8 floats composed (x1 y1 x2 y2) and
    (s1 t1 s2 t2). To avoid adding new struct fields to ClutterPaintOperation,
    which is a performance and memory sensitive structure, simply divide the
    array length by 8 (which is guaranteed to be correct).
    
    Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1637>

 clutter/clutter/clutter-paint-node-private.h |   1 +
 clutter/clutter/clutter-paint-node.c         | 112 +++++++++++++++++++++++++++
 clutter/clutter/clutter-paint-node.h         |   9 +++
 clutter/clutter/clutter-paint-nodes.c        |  18 +++++
 4 files changed, 140 insertions(+)
---
diff --git a/clutter/clutter/clutter-paint-node-private.h b/clutter/clutter/clutter-paint-node-private.h
index ee2b894391..b084e81d42 100644
--- a/clutter/clutter/clutter-paint-node-private.h
+++ b/clutter/clutter/clutter-paint-node-private.h
@@ -82,6 +82,7 @@ typedef enum
 {
   PAINT_OP_INVALID = 0,
   PAINT_OP_TEX_RECT,
+  PAINT_OP_TEX_RECTS,
   PAINT_OP_MULTITEX_RECT,
   PAINT_OP_PRIMITIVE
 } PaintOpCode;
diff --git a/clutter/clutter/clutter-paint-node.c b/clutter/clutter/clutter-paint-node.c
index 116cfa833e..4df3dac34b 100644
--- a/clutter/clutter/clutter-paint-node.c
+++ b/clutter/clutter/clutter-paint-node.c
@@ -777,6 +777,7 @@ clutter_paint_operation_clear (ClutterPaintOperation *op)
     case PAINT_OP_TEX_RECT:
       break;
 
+    case PAINT_OP_TEX_RECTS:
     case PAINT_OP_MULTITEX_RECT:
       g_clear_pointer (&op->coords, g_array_unref);
       break;
@@ -809,6 +810,36 @@ clutter_paint_op_init_tex_rect (ClutterPaintOperation *op,
   op->op.texrect[7] = y_2;
 }
 
+static inline void
+clutter_paint_op_init_tex_rects (ClutterPaintOperation *op,
+                                 const float           *coords,
+                                 unsigned int           n_rects,
+                                 gboolean               use_default_tex_coords)
+{
+  const unsigned int n_floats = n_rects * 8;
+
+  clutter_paint_operation_clear (op);
+
+  op->opcode = PAINT_OP_TEX_RECTS;
+  op->coords = g_array_sized_new (FALSE, FALSE, sizeof (float), n_floats);
+
+  if (use_default_tex_coords)
+    {
+      const float default_tex_coords[4] = { 0.0, 0.0, 1.0, 1.0 };
+      int i;
+
+      for (i = 0; i < n_rects; i++)
+        {
+          g_array_append_vals (op->coords, &coords[i * 4], 4);
+          g_array_append_vals (op->coords, default_tex_coords, 4);
+        }
+    }
+  else
+    {
+      g_array_append_vals (op->coords, coords, n_floats);
+    }
+}
+
 static inline void
 clutter_paint_op_init_multitex_rect (ClutterPaintOperation *op,
                                      const ClutterActorBox *rect,
@@ -934,6 +965,74 @@ clutter_paint_node_add_multitexture_rectangle (ClutterPaintNode      *node,
   g_array_append_val (node->operations, operation);
 }
 
+/**
+ * clutter_paint_node_add_rectangles:
+ * @node: a #ClutterPaintNode
+ * @coords: (in) (array length=n_rects) (transfer none): array of
+ *   coordinates containing groups of 4 float values: [x_1, y_1, x_2, y_2] that
+ *   are interpreted as two position coordinates; one for the top left of the
+ *   rectangle (x1, y1), and one for the bottom right of the rectangle
+ *   (x2, y2).
+ * @n_rects: number of rectangles defined in @coords.
+ *
+ * Adds a series of rectangles to @node.
+ *
+ * As a general rule for better performance its recommended to use this API
+ * instead of calling clutter_paint_node_add_rectangle() separately for
+ * multiple rectangles if all of the rectangles will be drawn together.
+ *
+ * See cogl_framebuffer_draw_rectangles().
+ */
+void
+clutter_paint_node_add_rectangles (ClutterPaintNode *node,
+                                   const float      *coords,
+                                   unsigned int      n_rects)
+{
+  ClutterPaintOperation operation = PAINT_OP_INIT;
+
+  g_return_if_fail (CLUTTER_IS_PAINT_NODE (node));
+  g_return_if_fail (coords != NULL);
+
+  clutter_paint_node_maybe_init_operations (node);
+
+  clutter_paint_op_init_tex_rects (&operation, coords, n_rects, TRUE);
+  g_array_append_val (node->operations, operation);
+}
+
+/**
+ * clutter_paint_node_add_texture_rectangles:
+ * @node: a #ClutterPaintNode
+ * @coords: (in) (array length=n_rects) (transfer none): array containing
+ *   groups of 8 float values: [x_1, y_1, x_2, y_2, s_1, t_1, s_2, t_2]
+ *   that have the same meaning as the arguments for
+ *   cogl_framebuffer_draw_textured_rectangle().
+ * @n_rects: number of rectangles defined in @coords.
+ *
+ * Adds a series of rectangles to @node.
+ *
+ * The given texture coordinates should always be normalized such that
+ * (0, 0) corresponds to the top left and (1, 1) corresponds to the
+ * bottom right. To map an entire texture across the rectangle pass
+ * in s_1=0, t_1=0, s_2=1, t_2=1.
+ *
+ * See cogl_framebuffer_draw_textured_rectangles().
+ */
+void
+clutter_paint_node_add_texture_rectangles (ClutterPaintNode *node,
+                                           const float      *coords,
+                                           unsigned int      n_rects)
+{
+  ClutterPaintOperation operation = PAINT_OP_INIT;
+
+  g_return_if_fail (CLUTTER_IS_PAINT_NODE (node));
+  g_return_if_fail (coords != NULL);
+
+  clutter_paint_node_maybe_init_operations (node);
+
+  clutter_paint_op_init_tex_rects (&operation, coords, n_rects, FALSE);
+  g_array_append_val (node->operations, operation);
+}
+
 /**
  * clutter_paint_node_add_primitive: (skip)
  * @node: a #ClutterPaintNode
@@ -1057,6 +1156,19 @@ clutter_paint_node_to_json (ClutterPaintNode *node)
               json_builder_end_array (builder);
               break;
 
+            case PAINT_OP_TEX_RECTS:
+              json_builder_set_member_name (builder, "texrects");
+              json_builder_begin_array (builder);
+
+              for (j = 0; i < op->coords->len; j++)
+                {
+                  float coord = g_array_index (op->coords, float, j);
+                  json_builder_add_double_value (builder, coord);
+                }
+
+              json_builder_end_array (builder);
+              break;
+
             case PAINT_OP_MULTITEX_RECT:
               json_builder_set_member_name (builder, "texrect");
               json_builder_begin_array (builder);
diff --git a/clutter/clutter/clutter-paint-node.h b/clutter/clutter/clutter-paint-node.h
index 7afc60f662..b9f174962e 100644
--- a/clutter/clutter/clutter-paint-node.h
+++ b/clutter/clutter/clutter-paint-node.h
@@ -83,6 +83,15 @@ void                   clutter_paint_node_add_multitexture_rectangle   (ClutterP
                                                                         const float            *text_coords,
                                                                         unsigned int            
text_coords_len);
 
+CLUTTER_EXPORT
+void                    clutter_paint_node_add_rectangles               (ClutterPaintNode *node,
+                                                                         const float      *coords,
+                                                                         unsigned int      n_rects);
+CLUTTER_EXPORT
+void                    clutter_paint_node_add_texture_rectangles       (ClutterPaintNode *node,
+                                                                         const float      *coords,
+                                                                         unsigned int      n_rects);
+
 CLUTTER_EXPORT
 void                    clutter_paint_node_add_primitive                (ClutterPaintNode      *node,
                                                                          CoglPrimitive         *primitive);
diff --git a/clutter/clutter/clutter-paint-nodes.c b/clutter/clutter/clutter-paint-nodes.c
index db42f2f3f3..9da5b450f0 100644
--- a/clutter/clutter/clutter-paint-nodes.c
+++ b/clutter/clutter/clutter-paint-nodes.c
@@ -467,6 +467,13 @@ clutter_pipeline_node_draw (ClutterPaintNode    *node,
                                                     op->op.texrect[7]);
           break;
 
+        case PAINT_OP_TEX_RECTS:
+          cogl_framebuffer_draw_textured_rectangles (fb,
+                                                     pnode->pipeline,
+                                                     (float *) op->coords->data,
+                                                     op->coords->len / 8);
+          break;
+
         case PAINT_OP_MULTITEX_RECT:
           cogl_framebuffer_draw_multitextured_rectangle (fb,
                                                          pnode->pipeline,
@@ -872,6 +879,7 @@ clutter_text_node_draw (ClutterPaintNode    *node,
             cogl_framebuffer_pop_clip (fb);
           break;
 
+        case PAINT_OP_TEX_RECTS:
         case PAINT_OP_MULTITEX_RECT:
         case PAINT_OP_PRIMITIVE:
         case PAINT_OP_INVALID:
@@ -1033,6 +1041,7 @@ clutter_clip_node_pre_draw (ClutterPaintNode    *node,
           retval = TRUE;
           break;
 
+        case PAINT_OP_TEX_RECTS:
         case PAINT_OP_MULTITEX_RECT:
         case PAINT_OP_PRIMITIVE:
         case PAINT_OP_INVALID:
@@ -1067,6 +1076,7 @@ clutter_clip_node_post_draw (ClutterPaintNode    *node,
           cogl_framebuffer_pop_clip (fb);
           break;
 
+        case PAINT_OP_TEX_RECTS:
         case PAINT_OP_MULTITEX_RECT:
         case PAINT_OP_PRIMITIVE:
         case PAINT_OP_INVALID:
@@ -1440,6 +1450,13 @@ clutter_layer_node_post_draw (ClutterPaintNode    *node,
                                                     op->op.texrect[7]);
           break;
 
+        case PAINT_OP_TEX_RECTS:
+          cogl_framebuffer_draw_textured_rectangles (fb,
+                                                     lnode->pipeline,
+                                                     (float *) op->coords->data,
+                                                     op->coords->len / 8);
+          break;
+
         case PAINT_OP_MULTITEX_RECT:
           cogl_framebuffer_draw_multitextured_rectangle (fb,
                                                          lnode->pipeline,
@@ -1695,6 +1712,7 @@ clutter_blit_node_draw (ClutterPaintNode    *node,
             }
           break;
 
+        case PAINT_OP_TEX_RECTS:
         case PAINT_OP_MULTITEX_RECT:
         case PAINT_OP_PRIMITIVE:
           break;


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