cogl-pango-display-list: Use cogl_rectangles_with_texture_coords

Instead of storing four vertices per rectangle in the array for a
texture node in the display list, it now only stores two in a format
that is acceptable to cogl_rectangles_with_texture_coords. That way
it can pass the array directly to that function. That function has the
advantage over cogl_rectangle that it doesn't need to validate the
pipeline for every quad so it should be slightly faster.

When the texture node is being rendered with a CoglPrimitive we now
map the buffer and expand the rectangles into 4 vertices as the data
is copied.

https://bugzilla.gnome.org/show_bug.cgi?id=656303

Reviewed-by: Robert Bragg <robert@linux.intel.com>
This commit is contained in:
Neil Roberts 2011-08-10 18:13:14 +01:00
parent 7c8c0f1023
commit df30641f0b

View File

@ -40,6 +40,7 @@ typedef enum
} CoglPangoDisplayListNodeType; } CoglPangoDisplayListNodeType;
typedef struct _CoglPangoDisplayListNode CoglPangoDisplayListNode; typedef struct _CoglPangoDisplayListNode CoglPangoDisplayListNode;
typedef struct _CoglPangoDisplayListRectangle CoglPangoDisplayListRectangle;
struct _CoglPangoDisplayList struct _CoglPangoDisplayList
{ {
@ -50,6 +51,13 @@ struct _CoglPangoDisplayList
CoglPangoPipelineCache *pipeline_cache; CoglPangoPipelineCache *pipeline_cache;
}; };
/* This matches the format expected by cogl_rectangles_with_texture_coords */
struct _CoglPangoDisplayListRectangle
{
float x_1, y_1, x_2, y_2;
float s_1, t_1, s_2, t_2;
};
struct _CoglPangoDisplayListNode struct _CoglPangoDisplayListNode
{ {
CoglPangoDisplayListNodeType type; CoglPangoDisplayListNodeType type;
@ -64,9 +72,10 @@ struct _CoglPangoDisplayListNode
struct struct
{ {
/* The texture to render these coords from */ /* The texture to render these coords from */
CoglHandle texture; CoglHandle texture;
/* Array of vertex data to render out of this texture */ /* Array of rectangles in the format expected by
GArray *verts; cogl_rectangles_with_texture_coords */
GArray *rectangles;
/* A primitive representing those vertices */ /* A primitive representing those vertices */
CoglPrimitive *primitive; CoglPrimitive *primitive;
} texture; } texture;
@ -132,7 +141,7 @@ _cogl_pango_display_list_add_texture (CoglPangoDisplayList *dl,
float tx_2, float ty_2) float tx_2, float ty_2)
{ {
CoglPangoDisplayListNode *node; CoglPangoDisplayListNode *node;
CoglVertexP2T2 *verts; CoglPangoDisplayListRectangle *rectangle;
/* Add to the last node if it is a texture node with the same /* Add to the last node if it is a texture node with the same
target texture */ target texture */
@ -160,38 +169,26 @@ _cogl_pango_display_list_add_texture (CoglPangoDisplayList *dl,
node->color = dl->color; node->color = dl->color;
node->pipeline = NULL; node->pipeline = NULL;
node->d.texture.texture = cogl_handle_ref (texture); node->d.texture.texture = cogl_handle_ref (texture);
node->d.texture.verts node->d.texture.rectangles
= g_array_new (FALSE, FALSE, sizeof (CoglVertexP2T2)); = g_array_new (FALSE, FALSE, sizeof (CoglPangoDisplayListRectangle));
node->d.texture.primitive = NULL; node->d.texture.primitive = NULL;
_cogl_pango_display_list_append_node (dl, node); _cogl_pango_display_list_append_node (dl, node);
} }
g_array_set_size (node->d.texture.verts, g_array_set_size (node->d.texture.rectangles,
node->d.texture.verts->len + 4); node->d.texture.rectangles->len + 1);
verts = &g_array_index (node->d.texture.verts, rectangle = &g_array_index (node->d.texture.rectangles,
CoglVertexP2T2, CoglPangoDisplayListRectangle,
node->d.texture.verts->len - 4); node->d.texture.rectangles->len - 1);
rectangle->x_1 = x_1;
verts->x = x_1; rectangle->y_1 = y_1;
verts->y = y_1; rectangle->x_2 = x_2;
verts->s = tx_1; rectangle->y_2 = y_2;
verts->t = ty_1; rectangle->s_1 = tx_1;
verts++; rectangle->t_1 = ty_1;
verts->x = x_1; rectangle->s_2 = tx_2;
verts->y = y_2; rectangle->t_2 = ty_2;
verts->s = tx_1;
verts->t = ty_2;
verts++;
verts->x = x_2;
verts->y = y_2;
verts->s = tx_2;
verts->t = ty_2;
verts++;
verts->x = x_2;
verts->y = y_1;
verts->s = tx_2;
verts->t = ty_1;
} }
void void
@ -241,20 +238,9 @@ _cogl_pango_display_list_add_trapezoid (CoglPangoDisplayList *dl,
static void static void
emit_rectangles_through_journal (CoglPangoDisplayListNode *node) emit_rectangles_through_journal (CoglPangoDisplayListNode *node)
{ {
int i; cogl_rectangles_with_texture_coords ((float *)
node->d.texture.rectangles->data,
for (i = 0; i < node->d.texture.verts->len; i += 4) node->d.texture.rectangles->len);
{
CoglVertexP2T2 *v0 =
&g_array_index (node->d.texture.verts,
CoglVertexP2T2, i);
CoglVertexP2T2 *v1 =
&g_array_index (node->d.texture.verts,
CoglVertexP2T2, i + 2);
cogl_rectangle_with_texture_coords (v0->x, v0->y, v1->x, v1->y,
v0->s, v0->t,
v1->s, v1->t);
}
} }
static void static void
@ -273,13 +259,69 @@ emit_vertex_buffer_geometry (CoglPangoDisplayListNode *node)
if (node->d.texture.primitive == NULL) if (node->d.texture.primitive == NULL)
{ {
CoglAttributeBuffer *buffer; CoglAttributeBuffer *buffer;
CoglVertexP2T2 *verts, *v;
int n_verts;
gboolean allocated = FALSE;
CoglAttribute *attributes[2]; CoglAttribute *attributes[2];
CoglPrimitive *prim; CoglPrimitive *prim;
int i;
n_verts = node->d.texture.rectangles->len * 4;
buffer buffer
= cogl_attribute_buffer_new (node->d.texture.verts->len = cogl_attribute_buffer_new (n_verts * sizeof (CoglVertexP2T2), NULL);
* sizeof (CoglVertexP2T2),
node->d.texture.verts->data); if ((verts = cogl_buffer_map (COGL_BUFFER (buffer),
COGL_BUFFER_ACCESS_WRITE,
COGL_BUFFER_MAP_HINT_DISCARD)) == NULL)
{
verts = g_new (CoglVertexP2T2, n_verts);
allocated = TRUE;
}
v = verts;
/* Copy the rectangles into the buffer and expand into four
vertices instead of just two */
for (i = 0; i < node->d.texture.rectangles->len; i++)
{
const CoglPangoDisplayListRectangle *rectangle
= &g_array_index (node->d.texture.rectangles,
CoglPangoDisplayListRectangle, i);
v->x = rectangle->x_1;
v->y = rectangle->y_1;
v->s = rectangle->s_1;
v->t = rectangle->t_1;
v++;
v->x = rectangle->x_1;
v->y = rectangle->y_2;
v->s = rectangle->s_1;
v->t = rectangle->t_2;
v++;
v->x = rectangle->x_2;
v->y = rectangle->y_2;
v->s = rectangle->s_2;
v->t = rectangle->t_2;
v++;
v->x = rectangle->x_2;
v->y = rectangle->y_1;
v->s = rectangle->s_2;
v->t = rectangle->t_1;
v++;
}
if (allocated)
{
cogl_buffer_set_data (COGL_BUFFER (buffer),
0, /* offset */
verts,
sizeof (CoglVertexP2T2) * n_verts);
g_free (verts);
}
else
cogl_buffer_unmap (COGL_BUFFER (buffer));
attributes[0] = cogl_attribute_new (buffer, attributes[0] = cogl_attribute_new (buffer,
"cogl_position_in", "cogl_position_in",
sizeof (CoglVertexP2T2), sizeof (CoglVertexP2T2),
@ -294,7 +336,7 @@ emit_vertex_buffer_geometry (CoglPangoDisplayListNode *node)
COGL_ATTRIBUTE_TYPE_FLOAT); COGL_ATTRIBUTE_TYPE_FLOAT);
prim = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES, prim = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES,
node->d.texture.verts->len, n_verts,
attributes, attributes,
2 /* n_attributes */); 2 /* n_attributes */);
@ -309,11 +351,11 @@ emit_vertex_buffer_geometry (CoglPangoDisplayListNode *node)
quads */ quads */
CoglIndices *indices = CoglIndices *indices =
cogl_get_rectangle_indices (node->d.texture.verts->len / 4); cogl_get_rectangle_indices (node->d.texture.rectangles->len);
cogl_primitive_set_indices (prim, indices); cogl_primitive_set_indices (prim, indices);
cogl_primitive_set_n_vertices (prim, cogl_primitive_set_n_vertices (prim,
node->d.texture.verts->len / 4 * 6); node->d.texture.rectangles->len * 6);
} }
node->d.texture.primitive = prim; node->d.texture.primitive = prim;
@ -332,9 +374,9 @@ _cogl_pango_display_list_render_texture (CoglPangoDisplayListNode *node)
/* For small runs of text like icon labels, we can get better performance /* For small runs of text like icon labels, we can get better performance
* going through the Cogl journal since text may then be batched together * going through the Cogl journal since text may then be batched together
* with other geometry. */ * with other geometry. */
/* FIXME: 100 is a number I plucked out of thin air; it would be good /* FIXME: 25 is a number I plucked out of thin air; it would be good
* to determine this empirically! */ * to determine this empirically! */
if (node->d.texture.verts->len < 100) if (node->d.texture.rectangles->len < 25)
emit_rectangles_through_journal (node); emit_rectangles_through_journal (node);
else else
emit_vertex_buffer_geometry (node); emit_vertex_buffer_geometry (node);
@ -422,7 +464,7 @@ _cogl_pango_display_list_node_free (CoglPangoDisplayListNode *node)
{ {
if (node->type == COGL_PANGO_DISPLAY_LIST_TEXTURE) if (node->type == COGL_PANGO_DISPLAY_LIST_TEXTURE)
{ {
g_array_free (node->d.texture.verts, TRUE); g_array_free (node->d.texture.rectangles, TRUE);
if (node->d.texture.texture != COGL_INVALID_HANDLE) if (node->d.texture.texture != COGL_INVALID_HANDLE)
cogl_handle_unref (node->d.texture.texture); cogl_handle_unref (node->d.texture.texture);
if (node->d.texture.primitive != NULL) if (node->d.texture.primitive != NULL)