pango-glyph-cache: Try to put glyphs in the global atlas
If mipmapping is disabled, it will now try to create a standalone atlas texture for a glyph rather than putting it in the atlas. If the atlas texture can't be created then it will fallback to the glyph cache.
This commit is contained in:
parent
9aaaee0308
commit
e3c57941bd
@ -30,6 +30,7 @@
|
|||||||
#include "cogl-pango-glyph-cache.h"
|
#include "cogl-pango-glyph-cache.h"
|
||||||
#include "cogl-pango-private.h"
|
#include "cogl-pango-private.h"
|
||||||
#include "cogl/cogl-atlas.h"
|
#include "cogl/cogl-atlas.h"
|
||||||
|
#include "cogl/cogl-atlas-texture-private.h"
|
||||||
|
|
||||||
typedef struct _CoglPangoGlyphCacheKey CoglPangoGlyphCacheKey;
|
typedef struct _CoglPangoGlyphCacheKey CoglPangoGlyphCacheKey;
|
||||||
|
|
||||||
@ -49,6 +50,10 @@ struct _CoglPangoGlyphCache
|
|||||||
optimization in _cogl_pango_glyph_cache_set_dirty_glyphs to avoid
|
optimization in _cogl_pango_glyph_cache_set_dirty_glyphs to avoid
|
||||||
iterating the hash table if we know none of them are dirty */
|
iterating the hash table if we know none of them are dirty */
|
||||||
gboolean has_dirty_glyphs;
|
gboolean has_dirty_glyphs;
|
||||||
|
|
||||||
|
/* Whether mipmapping is being used for this cache. This only
|
||||||
|
affects whether we decide to put the glyph in the global atlas */
|
||||||
|
gboolean use_mipmapping;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _CoglPangoGlyphCacheKey
|
struct _CoglPangoGlyphCacheKey
|
||||||
@ -118,6 +123,8 @@ cogl_pango_glyph_cache_new (gboolean use_mipmapping)
|
|||||||
|
|
||||||
cache->has_dirty_glyphs = FALSE;
|
cache->has_dirty_glyphs = FALSE;
|
||||||
|
|
||||||
|
cache->use_mipmapping = use_mipmapping;
|
||||||
|
|
||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,6 +186,86 @@ cogl_pango_glyph_cache_reorganize_cb (void *user_data)
|
|||||||
g_hook_list_invoke (&cache->reorganize_callbacks, FALSE);
|
g_hook_list_invoke (&cache->reorganize_callbacks, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
cogl_pango_glyph_cache_add_to_global_atlas (CoglPangoGlyphCache *cache,
|
||||||
|
PangoFont *font,
|
||||||
|
PangoGlyph glyph,
|
||||||
|
CoglPangoGlyphCacheValue *value)
|
||||||
|
{
|
||||||
|
CoglHandle texture;
|
||||||
|
|
||||||
|
/* If the cache is using mipmapping then we can't use the global
|
||||||
|
atlas because it would just get migrated back out */
|
||||||
|
if (cache->use_mipmapping)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
texture = _cogl_atlas_texture_new_with_size (value->draw_width,
|
||||||
|
value->draw_height,
|
||||||
|
COGL_TEXTURE_NONE,
|
||||||
|
COGL_PIXEL_FORMAT_RGBA_8888_PRE);
|
||||||
|
|
||||||
|
if (texture == COGL_INVALID_HANDLE)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
value->texture = texture;
|
||||||
|
value->tx1 = 0;
|
||||||
|
value->ty1 = 0;
|
||||||
|
value->tx2 = 1;
|
||||||
|
value->ty2 = 1;
|
||||||
|
value->tx_pixel = 0;
|
||||||
|
value->ty_pixel = 0;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
cogl_pango_glyph_cache_add_to_local_atlas (CoglPangoGlyphCache *cache,
|
||||||
|
PangoFont *font,
|
||||||
|
PangoGlyph glyph,
|
||||||
|
CoglPangoGlyphCacheValue *value)
|
||||||
|
{
|
||||||
|
CoglAtlas *atlas = NULL;
|
||||||
|
GSList *l;
|
||||||
|
|
||||||
|
/* Look for an atlas that can reserve the space */
|
||||||
|
for (l = cache->atlases; l; l = l->next)
|
||||||
|
if (_cogl_atlas_reserve_space (l->data,
|
||||||
|
value->draw_width + 1,
|
||||||
|
value->draw_height + 1,
|
||||||
|
value))
|
||||||
|
{
|
||||||
|
atlas = l->data;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we couldn't find one then start a new atlas */
|
||||||
|
if (atlas == NULL)
|
||||||
|
{
|
||||||
|
atlas = _cogl_atlas_new (COGL_PIXEL_FORMAT_A_8,
|
||||||
|
COGL_ATLAS_CLEAR_TEXTURE |
|
||||||
|
COGL_ATLAS_DISABLE_MIGRATION,
|
||||||
|
cogl_pango_glyph_cache_update_position_cb);
|
||||||
|
COGL_NOTE (ATLAS, "Created new atlas for glyphs: %p", atlas);
|
||||||
|
/* If we still can't reserve space then something has gone
|
||||||
|
seriously wrong so we'll just give up */
|
||||||
|
if (!_cogl_atlas_reserve_space (atlas,
|
||||||
|
value->draw_width + 1,
|
||||||
|
value->draw_height + 1,
|
||||||
|
value))
|
||||||
|
{
|
||||||
|
cogl_object_unref (atlas);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_cogl_atlas_add_reorganize_callback
|
||||||
|
(atlas, cogl_pango_glyph_cache_reorganize_cb, NULL, cache);
|
||||||
|
|
||||||
|
cache->atlases = g_slist_prepend (cache->atlases, atlas);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
CoglPangoGlyphCacheValue *
|
CoglPangoGlyphCacheValue *
|
||||||
cogl_pango_glyph_cache_lookup (CoglPangoGlyphCache *cache,
|
cogl_pango_glyph_cache_lookup (CoglPangoGlyphCache *cache,
|
||||||
gboolean create,
|
gboolean create,
|
||||||
@ -197,53 +284,31 @@ cogl_pango_glyph_cache_lookup (CoglPangoGlyphCache *cache,
|
|||||||
{
|
{
|
||||||
CoglPangoGlyphCacheKey *key;
|
CoglPangoGlyphCacheKey *key;
|
||||||
PangoRectangle ink_rect;
|
PangoRectangle ink_rect;
|
||||||
CoglAtlas *atlas = NULL;
|
|
||||||
GSList *l;
|
value = g_slice_new (CoglPangoGlyphCacheValue);
|
||||||
|
value->texture = COGL_INVALID_HANDLE;
|
||||||
|
value->dirty = TRUE;
|
||||||
|
|
||||||
pango_font_get_glyph_extents (font, glyph, &ink_rect, NULL);
|
pango_font_get_glyph_extents (font, glyph, &ink_rect, NULL);
|
||||||
pango_extents_to_pixels (&ink_rect, NULL);
|
pango_extents_to_pixels (&ink_rect, NULL);
|
||||||
|
|
||||||
value = g_slice_new (CoglPangoGlyphCacheValue);
|
|
||||||
value->texture = COGL_INVALID_HANDLE;
|
|
||||||
value->draw_x = ink_rect.x;
|
value->draw_x = ink_rect.x;
|
||||||
value->draw_y = ink_rect.y;
|
value->draw_y = ink_rect.y;
|
||||||
value->draw_width = ink_rect.width;
|
value->draw_width = ink_rect.width;
|
||||||
value->draw_height = ink_rect.height;
|
value->draw_height = ink_rect.height;
|
||||||
value->dirty = TRUE;
|
|
||||||
|
|
||||||
/* Look for an atlas that can reserve the space */
|
/* Try adding the glyph to the global atlas... */
|
||||||
for (l = cache->atlases; l; l = l->next)
|
if (!cogl_pango_glyph_cache_add_to_global_atlas (cache,
|
||||||
if (_cogl_atlas_reserve_space (l->data,
|
font,
|
||||||
ink_rect.width + 1, ink_rect.height + 1,
|
glyph,
|
||||||
value))
|
value) &&
|
||||||
{
|
!cogl_pango_glyph_cache_add_to_local_atlas (cache,
|
||||||
atlas = l->data;
|
font,
|
||||||
break;
|
glyph,
|
||||||
}
|
value))
|
||||||
|
|
||||||
/* If we couldn't find one then start a new atlas */
|
|
||||||
if (atlas == NULL)
|
|
||||||
{
|
{
|
||||||
atlas = _cogl_atlas_new (COGL_PIXEL_FORMAT_A_8,
|
cogl_pango_glyph_cache_value_free (value);
|
||||||
COGL_ATLAS_CLEAR_TEXTURE |
|
return NULL;
|
||||||
COGL_ATLAS_DISABLE_MIGRATION,
|
|
||||||
cogl_pango_glyph_cache_update_position_cb);
|
|
||||||
COGL_NOTE (ATLAS, "Created new atlas for glyphs: %p", atlas);
|
|
||||||
/* If we still can't reserve space then something has gone
|
|
||||||
seriously wrong so we'll just give up */
|
|
||||||
if (!_cogl_atlas_reserve_space (atlas,
|
|
||||||
ink_rect.width + 1,
|
|
||||||
ink_rect.height + 1, value))
|
|
||||||
{
|
|
||||||
cogl_object_unref (atlas);
|
|
||||||
cogl_pango_glyph_cache_value_free (value);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
_cogl_atlas_add_reorganize_callback
|
|
||||||
(atlas, cogl_pango_glyph_cache_reorganize_cb, NULL, cache);
|
|
||||||
|
|
||||||
cache->atlases = g_slist_prepend (cache->atlases, atlas);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
key = g_slice_new (CoglPangoGlyphCacheKey);
|
key = g_slice_new (CoglPangoGlyphCacheKey);
|
||||||
|
Loading…
Reference in New Issue
Block a user