[cogl] cogl-pango-display-list: Use cogl_rectangles_with_texture_coords



commit df30641f0bd6373541e74177a0e89963e1b6c8d4
Author: Neil Roberts <neil linux intel com>
Date:   Wed Aug 10 18:13:14 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.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=656303
    
    Reviewed-by: Robert Bragg <robert linux intel com>

 cogl-pango/cogl-pango-display-list.c |  150 ++++++++++++++++++++++------------
 1 files changed, 96 insertions(+), 54 deletions(-)
---
diff --git a/cogl-pango/cogl-pango-display-list.c b/cogl-pango/cogl-pango-display-list.c
index 382a83a..be62dac 100644
--- a/cogl-pango/cogl-pango-display-list.c
+++ b/cogl-pango/cogl-pango-display-list.c
@@ -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)



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