summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeil Roberts <neil@linux.intel.com>2011-08-11 12:56:08 +0100
committerNeil Roberts <neil@linux.intel.com>2011-08-11 12:56:08 +0100
commit2548aaa3ea3b3f15dc7593d290f186d3cab5569f (patch)
tree93c0a9faba12b5302488d6af4e7c3aba00c25680
parent40bd7226cfa9faefcfc1b57a13803d51804b99d9 (diff)
downloadclutter-wip/faster-pango-1.6.tar.gz
cogl-pango-display-list: Use cogl_rectangles_with_texture_coordswip/faster-pango-1.6
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.
-rw-r--r--clutter/cogl/pango/cogl-pango-display-list.c150
1 files changed, 96 insertions, 54 deletions
diff --git a/clutter/cogl/pango/cogl-pango-display-list.c b/clutter/cogl/pango/cogl-pango-display-list.c
index dd063873c..8ad388a7f 100644
--- a/clutter/cogl/pango/cogl-pango-display-list.c
+++ b/clutter/cogl/pango/cogl-pango-display-list.c
@@ -39,6 +39,7 @@ typedef enum
} CoglPangoDisplayListNodeType;
typedef struct _CoglPangoDisplayListNode CoglPangoDisplayListNode;
+typedef struct _CoglPangoDisplayListRectangle CoglPangoDisplayListRectangle;
struct _CoglPangoDisplayList
{
@@ -48,6 +49,13 @@ struct _CoglPangoDisplayList
GSList *last_node;
};
+/* 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
{
CoglPangoDisplayListNodeType type;
@@ -60,9 +68,10 @@ struct _CoglPangoDisplayListNode
struct
{
/* The texture to render these coords from */
- CoglHandle texture;
- /* Array of vertex data to render out of this texture */
- GArray *verts;
+ CoglHandle texture;
+ /* Array of rectangles in the format expected by
+ cogl_rectangles_with_texture_coords */
+ GArray *rectangles;
/* A primitive representing those vertices */
CoglPrimitive *primitive;
} texture;
@@ -124,7 +133,7 @@ _cogl_pango_display_list_add_texture (CoglPangoDisplayList *dl,
float tx_2, float ty_2)
{
CoglPangoDisplayListNode *node;
- CoglVertexP2T2 *verts;
+ CoglPangoDisplayListRectangle *rectangle;
/* Add to the last node if it is a texture node with the same
target texture */
@@ -151,38 +160,26 @@ _cogl_pango_display_list_add_texture (CoglPangoDisplayList *dl,
node->color_override = dl->color_override;
node->color = dl->color;
node->d.texture.texture = cogl_handle_ref (texture);
- node->d.texture.verts
- = g_array_new (FALSE, FALSE, sizeof (CoglVertexP2T2));
+ node->d.texture.rectangles
+ = g_array_new (FALSE, FALSE, sizeof (CoglPangoDisplayListRectangle));
node->d.texture.primitive = NULL;
_cogl_pango_display_list_append_node (dl, node);
}
- g_array_set_size (node->d.texture.verts,
- node->d.texture.verts->len + 4);
- verts = &g_array_index (node->d.texture.verts,
- CoglVertexP2T2,
- node->d.texture.verts->len - 4);
-
- verts->x = x_1;
- verts->y = y_1;
- verts->s = tx_1;
- verts->t = ty_1;
- verts++;
- verts->x = x_1;
- verts->y = y_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;
+ g_array_set_size (node->d.texture.rectangles,
+ node->d.texture.rectangles->len + 1);
+ rectangle = &g_array_index (node->d.texture.rectangles,
+ CoglPangoDisplayListRectangle,
+ node->d.texture.rectangles->len - 1);
+ rectangle->x_1 = x_1;
+ rectangle->y_1 = y_1;
+ rectangle->x_2 = x_2;
+ rectangle->y_2 = y_2;
+ rectangle->s_1 = tx_1;
+ rectangle->t_1 = ty_1;
+ rectangle->s_2 = tx_2;
+ rectangle->t_2 = ty_2;
}
void
@@ -230,20 +227,9 @@ _cogl_pango_display_list_add_trapezoid (CoglPangoDisplayList *dl,
static void
emit_rectangles_through_journal (CoglPangoDisplayListNode *node)
{
- int i;
-
- for (i = 0; i < node->d.texture.verts->len; i += 4)
- {
- 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);
- }
+ cogl_rectangles_with_texture_coords ((float *)
+ node->d.texture.rectangles->data,
+ node->d.texture.rectangles->len);
}
static void
@@ -260,13 +246,69 @@ emit_vertex_buffer_geometry (CoglPangoDisplayListNode *node)
if (node->d.texture.primitive == NULL)
{
CoglVertexArray *buffer;
+ CoglVertexP2T2 *verts, *v;
+ int n_verts;
+ gboolean allocated = FALSE;
CoglAttribute *attributes[3];
CoglPrimitive *prim;
+ int i;
+
+ n_verts = node->d.texture.rectangles->len * 4;
buffer
- = cogl_vertex_array_new (node->d.texture.verts->len
- * sizeof (CoglVertexP2T2),
- node->d.texture.verts->data);
+ = cogl_vertex_array_new (n_verts * sizeof (CoglVertexP2T2), NULL);
+
+ if ((verts = cogl_buffer_map ((CoglBuffer *) (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 ((CoglBuffer *) (buffer),
+ 0, /* offset */
+ verts,
+ sizeof (CoglVertexP2T2) * n_verts);
+ g_free (verts);
+ }
+ else
+ cogl_buffer_unmap ((CoglBuffer *) (buffer));
+
attributes[0] = cogl_attribute_new (buffer,
"cogl_position_in",
sizeof (CoglVertexP2T2),
@@ -283,7 +325,7 @@ emit_vertex_buffer_geometry (CoglPangoDisplayListNode *node)
prim = cogl_primitive_new_with_attributes_array
(COGL_VERTICES_MODE_TRIANGLES,
- node->d.texture.verts->len,
+ n_verts,
attributes);
#ifdef CLUTTER_COGL_HAS_GL
@@ -298,11 +340,11 @@ emit_vertex_buffer_geometry (CoglPangoDisplayListNode *node)
quads */
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_n_vertices (prim,
- node->d.texture.verts->len / 4 * 6);
+ node->d.texture.rectangles->len * 6);
}
#endif /* CLUTTER_COGL_HAS_GL */
@@ -332,9 +374,9 @@ _cogl_pango_display_list_render_texture (CoglMaterial *material,
/* 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
* 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! */
- if (node->d.texture.verts->len < 100)
+ if (node->d.texture.rectangles->len < 25)
emit_rectangles_through_journal (node);
else
emit_vertex_buffer_geometry (node);
@@ -416,7 +458,7 @@ _cogl_pango_display_list_node_free (CoglPangoDisplayListNode *node)
{
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)
cogl_handle_unref (node->d.texture.texture);
if (node->d.texture.primitive != NULL)