mirror of
https://github.com/brl/mutter.git
synced 2024-11-25 17:40:40 -05:00
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:
parent
7c8c0f1023
commit
df30641f0b
@ -40,6 +40,7 @@ typedef enum
|
||||
} CoglPangoDisplayListNodeType;
|
||||
|
||||
typedef struct _CoglPangoDisplayListNode CoglPangoDisplayListNode;
|
||||
typedef struct _CoglPangoDisplayListRectangle CoglPangoDisplayListRectangle;
|
||||
|
||||
struct _CoglPangoDisplayList
|
||||
{
|
||||
@ -50,6 +51,13 @@ struct _CoglPangoDisplayList
|
||||
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
|
||||
{
|
||||
CoglPangoDisplayListNodeType type;
|
||||
@ -64,9 +72,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;
|
||||
@ -132,7 +141,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 */
|
||||
@ -160,38 +169,26 @@ _cogl_pango_display_list_add_texture (CoglPangoDisplayList *dl,
|
||||
node->color = dl->color;
|
||||
node->pipeline = NULL;
|
||||
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
|
||||
@ -241,20 +238,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
|
||||
@ -273,13 +259,69 @@ emit_vertex_buffer_geometry (CoglPangoDisplayListNode *node)
|
||||
if (node->d.texture.primitive == NULL)
|
||||
{
|
||||
CoglAttributeBuffer *buffer;
|
||||
CoglVertexP2T2 *verts, *v;
|
||||
int n_verts;
|
||||
gboolean allocated = FALSE;
|
||||
CoglAttribute *attributes[2];
|
||||
CoglPrimitive *prim;
|
||||
int i;
|
||||
|
||||
n_verts = node->d.texture.rectangles->len * 4;
|
||||
|
||||
buffer
|
||||
= cogl_attribute_buffer_new (node->d.texture.verts->len
|
||||
* sizeof (CoglVertexP2T2),
|
||||
node->d.texture.verts->data);
|
||||
= cogl_attribute_buffer_new (n_verts * sizeof (CoglVertexP2T2), NULL);
|
||||
|
||||
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,
|
||||
"cogl_position_in",
|
||||
sizeof (CoglVertexP2T2),
|
||||
@ -294,7 +336,7 @@ emit_vertex_buffer_geometry (CoglPangoDisplayListNode *node)
|
||||
COGL_ATTRIBUTE_TYPE_FLOAT);
|
||||
|
||||
prim = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES,
|
||||
node->d.texture.verts->len,
|
||||
n_verts,
|
||||
attributes,
|
||||
2 /* n_attributes */);
|
||||
|
||||
@ -309,11 +351,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);
|
||||
}
|
||||
|
||||
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
|
||||
* 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);
|
||||
@ -422,7 +464,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)
|
||||
|
Loading…
Reference in New Issue
Block a user