mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2025-12-31 13:40:14 +01:00
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@chris-wilson.co.uk>
This commit is contained in:
parent
98335b4390
commit
d828c724c0
5 changed files with 81 additions and 90 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -54,10 +54,29 @@
|
|||
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,
|
||||
|
|
@ -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);
|
||||
|
||||
priv->node.owner = NULL;
|
||||
if (! priv->node.pinned) {
|
||||
/* XXX thread-safety? Probably ok due to the frozen scaled-font. */
|
||||
_cairo_gl_node_destroy (&priv->node);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue