diff options
author | Neil Roberts <neil@linux.intel.com> | 2011-08-11 12:56:08 +0100 |
---|---|---|
committer | Neil Roberts <neil@linux.intel.com> | 2011-08-11 12:56:08 +0100 |
commit | 2548aaa3ea3b3f15dc7593d290f186d3cab5569f (patch) | |
tree | 93c0a9faba12b5302488d6af4e7c3aba00c25680 | |
parent | 40bd7226cfa9faefcfc1b57a13803d51804b99d9 (diff) | |
download | clutter-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.c | 150 |
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) |