[clutter/wip/faster-pango-1.6: 2/2] cogl-pango-display-list: Use cogl_rectangles_with_texture_coords



commit 2548aaa3ea3b3f15dc7593d290f186d3cab5569f
Author: Neil Roberts <neil linux intel com>
Date:   Thu Aug 11 12:56:08 2011 +0100

    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.

 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 dd06387..8ad388a 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)



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]