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>
This commit is contained in:
parent
2cef2b6b1e
commit
2f01ef69e3
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user