[cairo-commit] src/cairo-gl-composite.c src/cairo-gl-glyphs.c src/cairo-gl-private.h src/cairo-rtree.c src/cairo-rtree-private.h

Chris Wilson ickle at kemper.freedesktop.org
Wed Dec 7 10:22:37 PST 2011


 src/cairo-gl-composite.c  |    4 +
 src/cairo-gl-glyphs.c     |   55 +++++++++++++------------
 src/cairo-gl-private.h    |    7 +++
 src/cairo-rtree-private.h |    6 +-
 src/cairo-rtree.c         |   99 +++++++++++++++++-----------------------------
 5 files changed, 81 insertions(+), 90 deletions(-)

New commits:
commit d828c724c06cea151fc87ef2bb98e57be0cdba46
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Dec 7 17:47:34 2011 +0000

    gl: Decouple the glyph upon eviction
    
    In order to decouple the texture node from the scaled glyph cache, we
    need to add a callback from the rtree for when the node is removed.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index 777a714..ebd9455 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -614,6 +614,7 @@ void
 _cairo_gl_composite_flush (cairo_gl_context_t *ctx)
 {
     unsigned int count;
+    int i;
 
     if (_cairo_gl_context_is_flushed (ctx))
         return;
@@ -637,6 +638,9 @@ _cairo_gl_composite_flush (cairo_gl_context_t *ctx)
     } else {
         _cairo_gl_composite_draw (ctx, count);
     }
+
+    for (i = 0; i < ARRAY_LENGTH (&ctx->glyph_cache); i++)
+	_cairo_gl_glyph_cache_unlock (&ctx->glyph_cache[i]);
 }
 
 static void
diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c
index 63678ff..c553d7d 100644
--- a/src/cairo-gl-glyphs.c
+++ b/src/cairo-gl-glyphs.c
@@ -54,11 +54,30 @@
 typedef struct _cairo_gl_glyph {
     cairo_rtree_node_t node;
     cairo_scaled_glyph_private_t base;
+    cairo_scaled_glyph_t *glyph;
     cairo_gl_glyph_cache_t *cache;
     struct { float x, y; } p1, p2;
 } cairo_gl_glyph_t;
 
 static void
+_cairo_gl_node_destroy (cairo_rtree_node_t *node)
+{
+    cairo_gl_glyph_t *priv = cairo_container_of (node, cairo_gl_glyph_t, node);
+    cairo_scaled_glyph_t *glyph;
+
+    glyph = priv->glyph;
+    if (glyph == NULL)
+	    return;
+
+    if (glyph->dev_private_key == priv->cache) {
+	    glyph->dev_private = NULL;
+	    glyph->dev_private_key = NULL;
+    }
+    cairo_list_del (&priv->base.link);
+    priv->glyph = NULL;
+}
+
+static void
 _cairo_gl_glyph_fini (cairo_scaled_glyph_private_t *glyph_private,
 		      cairo_scaled_glyph_t *scaled_glyph,
 		      cairo_scaled_font_t  *scaled_font)
@@ -67,13 +86,15 @@ _cairo_gl_glyph_fini (cairo_scaled_glyph_private_t *glyph_private,
 						 cairo_gl_glyph_t,
 						 base);
 
-    cairo_list_del (&glyph_private->link);
+    assert (priv->glyph);
+
+    _cairo_gl_node_destroy (&priv->node);
 
-    priv->node.owner = NULL;
-    if (! priv->node.pinned) {
-	/* XXX thread-safety? Probably ok due to the frozen scaled-font. */
+    /* XXX thread-safety? Probably ok due to the frozen scaled-font. */
+    if (! priv->node.pinned)
 	_cairo_rtree_node_remove (&priv->cache->rtree, &priv->node);
-    }
+
+    assert (priv->glyph == NULL);
 }
 
 static cairo_int_status_t
@@ -119,11 +140,11 @@ _cairo_gl_glyph_cache_add_glyph (cairo_gl_context_t *ctx,
 
     glyph_private = (cairo_gl_glyph_t *) node;
     glyph_private->cache = cache;
+    glyph_private->glyph = scaled_glyph;
     _cairo_scaled_glyph_attach_private (scaled_glyph,
 					&glyph_private->base,
 					cache,
 					_cairo_gl_glyph_fini);
-    glyph_private->node.owner = (void*)scaled_glyph;
 
     scaled_glyph->dev_private = glyph_private;
     scaled_glyph->dev_private_key = cache;
@@ -198,12 +219,6 @@ cairo_gl_context_get_glyph_cache (cairo_gl_context_t *ctx,
     return CAIRO_STATUS_SUCCESS;
 }
 
-static void
-_cairo_gl_glyph_cache_unlock (cairo_gl_glyph_cache_t *cache)
-{
-    _cairo_rtree_unpin (&cache->rtree);
-}
-
 static cairo_status_t
 render_glyphs (cairo_gl_surface_t	*dst,
 	       int dst_x, int dst_y,
@@ -445,26 +460,14 @@ _cairo_gl_glyph_cache_init (cairo_gl_glyph_cache_t *cache)
 		       GLYPH_CACHE_WIDTH,
 		       GLYPH_CACHE_HEIGHT,
 		       GLYPH_CACHE_MIN_SIZE,
-		       sizeof (cairo_gl_glyph_t));
-}
-
-static void
-_cairo_gl_glyph_cache_fini_glyph (cairo_rtree_node_t *node,
-				  void *cache)
-{
-    cairo_gl_glyph_t *glyph_private = (cairo_gl_glyph_t *) node;
-    if (glyph_private->node.owner) {
-	cairo_list_del (&glyph_private->base.link);
-	glyph_private->node.owner = NULL;
-    }
+		       sizeof (cairo_gl_glyph_t),
+		       _cairo_gl_node_destroy);
 }
 
 void
 _cairo_gl_glyph_cache_fini (cairo_gl_context_t *ctx,
 			    cairo_gl_glyph_cache_t *cache)
 {
-    _cairo_rtree_foreach (&cache->rtree,
-			  _cairo_gl_glyph_cache_fini_glyph, NULL);
     _cairo_rtree_fini (&cache->rtree);
     cairo_surface_destroy (&cache->surface->base);
 }
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 856f522..05d1567 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -721,6 +721,13 @@ source_to_operand (cairo_surface_t *surface)
     return source ? &source->operand : NULL;
 }
 
+static inline void
+_cairo_gl_glyph_cache_unlock (cairo_gl_glyph_cache_t *cache)
+{
+    _cairo_rtree_unpin (&cache->rtree);
+}
+
+
 slim_hidden_proto (cairo_gl_surface_create);
 slim_hidden_proto (cairo_gl_surface_create_for_texture);
 
diff --git a/src/cairo-rtree-private.h b/src/cairo-rtree-private.h
index 3289f79..b8db477 100644
--- a/src/cairo-rtree-private.h
+++ b/src/cairo-rtree-private.h
@@ -52,7 +52,6 @@ enum {
 
 typedef struct _cairo_rtree_node {
     struct _cairo_rtree_node *children[4], *parent;
-    void **owner;
     cairo_list_t link;
     uint16_t pinned;
     uint16_t state;
@@ -66,6 +65,7 @@ typedef struct _cairo_rtree {
     cairo_list_t pinned;
     cairo_list_t available;
     cairo_list_t evictable;
+    void (*destroy) (cairo_rtree_node_t *);
     cairo_freepool_t node_freepool;
 } cairo_rtree_t;
 
@@ -98,7 +98,8 @@ _cairo_rtree_init (cairo_rtree_t	*rtree,
 	           int			 width,
 		   int			 height,
 		   int			 min_size,
-		   int			 node_size);
+		   int			 node_size,
+		   void (*destroy)(cairo_rtree_node_t *));
 
 cairo_private cairo_int_status_t
 _cairo_rtree_insert (cairo_rtree_t	     *rtree,
@@ -120,6 +121,7 @@ _cairo_rtree_foreach (cairo_rtree_t *rtree,
 static inline void *
 _cairo_rtree_pin (cairo_rtree_t *rtree, cairo_rtree_node_t *node)
 {
+    assert (node->state == CAIRO_RTREE_NODE_OCCUPIED);
     if (! node->pinned) {
 	cairo_list_move (&node->link, &rtree->pinned);
 	node->pinned = 1;
diff --git a/src/cairo-rtree.c b/src/cairo-rtree.c
index 94af45b..dbc0409 100644
--- a/src/cairo-rtree.c
+++ b/src/cairo-rtree.c
@@ -57,7 +57,6 @@ _cairo_rtree_node_create (cairo_rtree_t		 *rtree,
 
     node->children[0] = NULL;
     node->parent = parent;
-    node->owner  = NULL;
     node->state  = CAIRO_RTREE_NODE_AVAILABLE;
     node->pinned = FALSE;
     node->x	 = x;
@@ -78,8 +77,7 @@ _cairo_rtree_node_destroy (cairo_rtree_t *rtree, cairo_rtree_node_t *node)
     cairo_list_del (&node->link);
 
     if (node->state == CAIRO_RTREE_NODE_OCCUPIED) {
-	if (node->owner != NULL)
-	    *node->owner = NULL;
+	rtree->destroy (node);
     } else {
 	for (i = 0; i < 4 && node->children[i] != NULL; i++)
 	    _cairo_rtree_node_destroy (rtree, node->children[i]);
@@ -186,6 +184,8 @@ _cairo_rtree_node_remove (cairo_rtree_t *rtree, cairo_rtree_node_t *node)
     assert (node->state == CAIRO_RTREE_NODE_OCCUPIED);
     assert (node->pinned == FALSE);
 
+    rtree->destroy (node);
+
     node->state = CAIRO_RTREE_NODE_AVAILABLE;
     cairo_list_move (&node->link, &rtree->available);
 
@@ -225,15 +225,22 @@ _cairo_rtree_evict_random (cairo_rtree_t	 *rtree,
 		           int			  height,
 		           cairo_rtree_node_t		**out)
 {
+    cairo_int_status_t ret = CAIRO_INT_STATUS_UNSUPPORTED;
     cairo_rtree_node_t *node, *next;
+    cairo_list_t tmp_pinned;
     int i, cnt;
 
+    cairo_list_init (&tmp_pinned);
+
     /* propagate pinned from children to root */
-    cairo_list_foreach_entry_safe (node, next, cairo_rtree_node_t,
-				   &rtree->pinned, link)
-    {
-	if (node->parent != NULL)
-	    _cairo_rtree_pin (rtree, node->parent);
+    cairo_list_foreach_entry_safe (node, next,
+				   cairo_rtree_node_t, &rtree->pinned, link) {
+	node = node->parent;
+	while (node && ! node->pinned) {
+	    node->pinned = 1;
+	    cairo_list_move (&node->link, &tmp_pinned);
+	    node = node->parent;
+	}
     }
 
     cnt = 0;
@@ -245,7 +252,7 @@ _cairo_rtree_evict_random (cairo_rtree_t	 *rtree,
     }
 
     if (cnt == 0)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
+	goto out;
 
     cnt = hars_petruska_f54_1_random () % cnt;
     cairo_list_foreach_entry (node, cairo_rtree_node_t,
@@ -253,8 +260,7 @@ _cairo_rtree_evict_random (cairo_rtree_t	 *rtree,
     {
 	if (node->width >= width && node->height >= height && cnt-- == 0) {
 	    if (node->state == CAIRO_RTREE_NODE_OCCUPIED) {
-		if (node->owner != NULL)
-		    *node->owner = NULL;
+		rtree->destroy (node);
 	    } else {
 		for (i = 0; i < 4 && node->children[i] != NULL; i++)
 		    _cairo_rtree_node_destroy (rtree, node->children[i]);
@@ -265,60 +271,29 @@ _cairo_rtree_evict_random (cairo_rtree_t	 *rtree,
 	    cairo_list_move (&node->link, &rtree->available);
 
 	    *out = node;
-	    return CAIRO_STATUS_SUCCESS;
+	    ret = CAIRO_STATUS_SUCCESS;
+	    break;
 	}
     }
 
-    return CAIRO_INT_STATUS_UNSUPPORTED;
+out:
+    while (! cairo_list_is_empty (&tmp_pinned)) {
+	node = cairo_list_first_entry (&tmp_pinned, cairo_rtree_node_t, link);
+	node->pinned = 0;
+	cairo_list_move (&node->link, &rtree->evictable);
+    }
+    return ret;
 }
 
 void
 _cairo_rtree_unpin (cairo_rtree_t *rtree)
 {
-    cairo_rtree_node_t *node, *next;
-    cairo_list_t can_collapse;
-
-    if (cairo_list_is_empty (&rtree->pinned))
-	return;
-
-    cairo_list_init (&can_collapse);
-
-    cairo_list_foreach_entry_safe (node, next,
-	                           cairo_rtree_node_t,
-				   &rtree->pinned,
-				   link)
-    {
-	node->pinned = FALSE;
-	if (node->state == CAIRO_RTREE_NODE_OCCUPIED && node->owner == NULL) {
-	    cairo_bool_t all_available;
-	    int i;
-
-	    node->state = CAIRO_RTREE_NODE_AVAILABLE;
-	    cairo_list_move (&node->link, &rtree->available);
-
-	    all_available = TRUE;
-	    node = node->parent;
-	    for (i = 0; i < 4 && node->children[i] != NULL && all_available; i++)
-		all_available &= node->children[i]->state == CAIRO_RTREE_NODE_AVAILABLE;
-
-	    if (all_available) {
-		cairo_list_move (&node->link, &can_collapse);
-		for (i = 0;  i < 4 && node->children[i] != NULL; i++)
-		    cairo_list_del (&node->children[i]->link);
-	    }
-	}
-	else
-	{
-	    cairo_list_move (&node->link, &rtree->evictable);
-	}
-    }
-
-    cairo_list_foreach_entry_safe (node, next,
-	                           cairo_rtree_node_t,
-				   &can_collapse,
-				   link)
-    {
-	_cairo_rtree_node_collapse (rtree, node);
+    while (! cairo_list_is_empty (&rtree->pinned)) {
+	cairo_rtree_node_t *node = cairo_list_first_entry (&rtree->pinned,
+							   cairo_rtree_node_t,
+							   link);
+	node->pinned = 0;
+	cairo_list_move (&node->link, &rtree->evictable);
     }
 }
 
@@ -327,7 +302,8 @@ _cairo_rtree_init (cairo_rtree_t	*rtree,
 	           int			 width,
 		   int			 height,
 		   int			 min_size,
-		   int			 node_size)
+		   int			 node_size,
+		   void (*destroy) (cairo_rtree_node_t *))
 {
     assert (node_size >= (int) sizeof (cairo_rtree_node_t));
     _cairo_freepool_init (&rtree->node_freepool, node_size);
@@ -337,6 +313,7 @@ _cairo_rtree_init (cairo_rtree_t	*rtree,
     cairo_list_init (&rtree->evictable);
 
     rtree->min_size = min_size;
+    rtree->destroy = destroy;
 
     memset (&rtree->root, 0, sizeof (rtree->root));
     rtree->root.width = width;
@@ -351,8 +328,7 @@ _cairo_rtree_reset (cairo_rtree_t *rtree)
     int i;
 
     if (rtree->root.state == CAIRO_RTREE_NODE_OCCUPIED) {
-	if (rtree->root.owner != NULL)
-	    *rtree->root.owner = NULL;
+	rtree->destroy (&rtree->root);
     } else {
 	for (i = 0; i < 4 && rtree->root.children[i] != NULL; i++)
 	    _cairo_rtree_node_destroy (rtree, rtree->root.children[i]);
@@ -402,8 +378,7 @@ _cairo_rtree_fini (cairo_rtree_t *rtree)
     int i;
 
     if (rtree->root.state == CAIRO_RTREE_NODE_OCCUPIED) {
-	if (rtree->root.owner != NULL)
-	    *rtree->root.owner = NULL;
+	rtree->destroy (&rtree->root);
     } else {
 	for (i = 0; i < 4 && rtree->root.children[i] != NULL; i++)
 	    _cairo_rtree_node_destroy (rtree, rtree->root.children[i]);


More information about the cairo-commit mailing list