cogl-pango-display-list: Use CoglPrimitive instead of CoglVertexBuffer

When rendering text through a VBO, CoglPangoDisplayList now uses the
CoglPrimitive API instead of CoglVertexBuffer. CoglVertexBuffer is
just a layer on top of the attribute buffer API anyway so it should be
slightly faster.

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 17:03:48 +01:00
parent 9270412495
commit 7c8c0f1023

View File

@ -40,7 +40,6 @@ typedef enum
} CoglPangoDisplayListNodeType; } CoglPangoDisplayListNodeType;
typedef struct _CoglPangoDisplayListNode CoglPangoDisplayListNode; typedef struct _CoglPangoDisplayListNode CoglPangoDisplayListNode;
typedef struct _CoglPangoDisplayListVertex CoglPangoDisplayListVertex;
struct _CoglPangoDisplayList struct _CoglPangoDisplayList
{ {
@ -68,8 +67,8 @@ struct _CoglPangoDisplayListNode
CoglHandle texture; CoglHandle texture;
/* Array of vertex data to render out of this texture */ /* Array of vertex data to render out of this texture */
GArray *verts; GArray *verts;
/* A VBO representing those vertices */ /* A primitive representing those vertices */
CoglHandle vertex_buffer; CoglPrimitive *primitive;
} texture; } texture;
struct struct
@ -90,11 +89,6 @@ struct _CoglPangoDisplayListNode
} d; } d;
}; };
struct _CoglPangoDisplayListVertex
{
float x, y, t_x, t_y;
};
CoglPangoDisplayList * CoglPangoDisplayList *
_cogl_pango_display_list_new (CoglPangoPipelineCache *pipeline_cache) _cogl_pango_display_list_new (CoglPangoPipelineCache *pipeline_cache)
{ {
@ -138,7 +132,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;
CoglPangoDisplayListVertex *verts; CoglVertexP2T2 *verts;
/* 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 */
@ -150,10 +144,10 @@ _cogl_pango_display_list_add_texture (CoglPangoDisplayList *dl,
: !node->color_override)) : !node->color_override))
{ {
/* Get rid of the vertex buffer so that it will be recreated */ /* Get rid of the vertex buffer so that it will be recreated */
if (node->d.texture.vertex_buffer != COGL_INVALID_HANDLE) if (node->d.texture.primitive != NULL)
{ {
cogl_handle_unref (node->d.texture.vertex_buffer); cogl_object_unref (node->d.texture.primitive);
node->d.texture.vertex_buffer = COGL_INVALID_HANDLE; node->d.texture.primitive = NULL;
} }
} }
else else
@ -167,8 +161,8 @@ _cogl_pango_display_list_add_texture (CoglPangoDisplayList *dl,
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.verts
= g_array_new (FALSE, FALSE, sizeof (CoglPangoDisplayListVertex)); = g_array_new (FALSE, FALSE, sizeof (CoglVertexP2T2));
node->d.texture.vertex_buffer = COGL_INVALID_HANDLE; node->d.texture.primitive = NULL;
_cogl_pango_display_list_append_node (dl, node); _cogl_pango_display_list_append_node (dl, node);
} }
@ -176,28 +170,28 @@ _cogl_pango_display_list_add_texture (CoglPangoDisplayList *dl,
g_array_set_size (node->d.texture.verts, g_array_set_size (node->d.texture.verts,
node->d.texture.verts->len + 4); node->d.texture.verts->len + 4);
verts = &g_array_index (node->d.texture.verts, verts = &g_array_index (node->d.texture.verts,
CoglPangoDisplayListVertex, CoglVertexP2T2,
node->d.texture.verts->len - 4); node->d.texture.verts->len - 4);
verts->x = x_1; verts->x = x_1;
verts->y = y_1; verts->y = y_1;
verts->t_x = tx_1; verts->s = tx_1;
verts->t_y = ty_1; verts->t = ty_1;
verts++; verts++;
verts->x = x_1; verts->x = x_1;
verts->y = y_2; verts->y = y_2;
verts->t_x = tx_1; verts->s = tx_1;
verts->t_y = ty_2; verts->t = ty_2;
verts++; verts++;
verts->x = x_2; verts->x = x_2;
verts->y = y_2; verts->y = y_2;
verts->t_x = tx_2; verts->s = tx_2;
verts->t_y = ty_2; verts->t = ty_2;
verts++; verts++;
verts->x = x_2; verts->x = x_2;
verts->y = y_1; verts->y = y_1;
verts->t_x = tx_2; verts->s = tx_2;
verts->t_y = ty_1; verts->t = ty_1;
} }
void void
@ -251,15 +245,15 @@ emit_rectangles_through_journal (CoglPangoDisplayListNode *node)
for (i = 0; i < node->d.texture.verts->len; i += 4) for (i = 0; i < node->d.texture.verts->len; i += 4)
{ {
CoglPangoDisplayListVertex *v0 = CoglVertexP2T2 *v0 =
&g_array_index (node->d.texture.verts, &g_array_index (node->d.texture.verts,
CoglPangoDisplayListVertex, i); CoglVertexP2T2, i);
CoglPangoDisplayListVertex *v1 = CoglVertexP2T2 *v1 =
&g_array_index (node->d.texture.verts, &g_array_index (node->d.texture.verts,
CoglPangoDisplayListVertex, i + 2); CoglVertexP2T2, i + 2);
cogl_rectangle_with_texture_coords (v0->x, v0->y, v1->x, v1->y, cogl_rectangle_with_texture_coords (v0->x, v0->y, v1->x, v1->y,
v0->t_x, v0->t_y, v0->s, v0->t,
v1->t_x, v1->t_y); v1->s, v1->t);
} }
} }
@ -276,47 +270,60 @@ emit_vertex_buffer_geometry (CoglPangoDisplayListNode *node)
* be re-used avoiding the repeated cost of validating the data and * be re-used avoiding the repeated cost of validating the data and
* mapping it into the GPU... */ * mapping it into the GPU... */
if (node->d.texture.vertex_buffer == COGL_INVALID_HANDLE) if (node->d.texture.primitive == NULL)
{ {
CoglHandle vb = cogl_vertex_buffer_new (node->d.texture.verts->len); CoglAttributeBuffer *buffer;
CoglAttribute *attributes[2];
CoglPrimitive *prim;
cogl_vertex_buffer_add (vb, "gl_Vertex", 2, buffer
COGL_ATTRIBUTE_TYPE_FLOAT, FALSE, = cogl_attribute_buffer_new (node->d.texture.verts->len
sizeof (CoglPangoDisplayListVertex), * sizeof (CoglVertexP2T2),
&g_array_index (node->d.texture.verts, node->d.texture.verts->data);
CoglPangoDisplayListVertex, 0).x); attributes[0] = cogl_attribute_new (buffer,
cogl_vertex_buffer_add (vb, "gl_MultiTexCoord0", 2, "cogl_position_in",
COGL_ATTRIBUTE_TYPE_FLOAT, FALSE, sizeof (CoglVertexP2T2),
sizeof (CoglPangoDisplayListVertex), G_STRUCT_OFFSET (CoglVertexP2T2, x),
&g_array_index (node->d.texture.verts, 2, /* n_components */
CoglPangoDisplayListVertex, COGL_ATTRIBUTE_TYPE_FLOAT);
0).t_x); attributes[1] = cogl_attribute_new (buffer,
cogl_vertex_buffer_submit (vb); "cogl_tex_coord0_in",
sizeof (CoglVertexP2T2),
G_STRUCT_OFFSET (CoglVertexP2T2, s),
2, /* n_components */
COGL_ATTRIBUTE_TYPE_FLOAT);
node->d.texture.vertex_buffer = vb; prim = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES,
} node->d.texture.verts->len,
attributes,
2 /* n_attributes */);
#ifdef CLUTTER_COGL_HAS_GL #ifdef CLUTTER_COGL_HAS_GL
if (ctx->driver == COGL_DRIVER_GL) if (ctx->driver == COGL_DRIVER_GL)
cogl_vertex_buffer_draw (node->d.texture.vertex_buffer, cogl_primitive_set_mode (prim, GL_QUADS);
GL_QUADS, else
0, node->d.texture.verts->len);
else
#endif #endif
{ {
/* GLES doesn't support GL_QUADS so instead we use a VBO with /* GLES doesn't support GL_QUADS so instead we use a VBO
indexed vertices to generate GL_TRIANGLES from the quads */ with indexed vertices to generate GL_TRIANGLES from the
quads */
int n_indices = node->d.texture.verts->len / 4 * 6; CoglIndices *indices =
CoglHandle indices_vbo cogl_get_rectangle_indices (node->d.texture.verts->len / 4);
= cogl_vertex_buffer_indices_get_for_quads (n_indices);
cogl_vertex_buffer_draw_elements (node->d.texture.vertex_buffer, cogl_primitive_set_indices (prim, indices);
COGL_VERTICES_MODE_TRIANGLES, cogl_primitive_set_n_vertices (prim,
indices_vbo, node->d.texture.verts->len / 4 * 6);
0, node->d.texture.verts->len - 1, }
0, n_indices);
node->d.texture.primitive = prim;
cogl_object_unref (buffer);
cogl_object_unref (attributes[0]);
cogl_object_unref (attributes[1]);
} }
cogl_primitive_draw (node->d.texture.primitive);
} }
static void static void
@ -418,8 +425,8 @@ _cogl_pango_display_list_node_free (CoglPangoDisplayListNode *node)
g_array_free (node->d.texture.verts, TRUE); g_array_free (node->d.texture.verts, 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.vertex_buffer != COGL_INVALID_HANDLE) if (node->d.texture.primitive != NULL)
cogl_handle_unref (node->d.texture.vertex_buffer); cogl_object_unref (node->d.texture.primitive);
} }
if (node->pipeline) if (node->pipeline)