cogl-atlas: Support multiple formats and clearing the texture

_cogl_atlas_new now has two extra parameters to specify the format of
the textures it creates as well as a set of flags to modify the
behavious of the atlas. One of the flags causes the new textures to be
cleared and the other causes migration to avoid actually copying the
textures. This is needed to use CoglAtlas from the pango glyph cache
because it needs to use COGL_PIXEL_A_8 and to clear the textures as it
does not fill in the gaps between glyphs. It needs to avoid copying
the textures so that it can work on GL implementations without FBO
support.
This commit is contained in:
Neil Roberts 2010-08-05 13:24:02 +01:00
parent 9b2f8179f0
commit 047227fbd7
3 changed files with 86 additions and 26 deletions

View File

@ -121,7 +121,9 @@ _cogl_atlas_texture_get_atlas (void)
if (ctx->atlas == COGL_INVALID_HANDLE) if (ctx->atlas == COGL_INVALID_HANDLE)
{ {
ctx->atlas = _cogl_atlas_new (_cogl_atlas_texture_update_position_cb); ctx->atlas = _cogl_atlas_new (COGL_PIXEL_FORMAT_RGBA_8888,
0,
_cogl_atlas_texture_update_position_cb);
_cogl_atlas_add_reorganize_callback (ctx->atlas, _cogl_atlas_add_reorganize_callback (ctx->atlas,
_cogl_atlas_texture_reorganize_cb, _cogl_atlas_texture_reorganize_cb,

View File

@ -199,13 +199,17 @@ _cogl_atlas_blit_end (CoglAtlasBlitData *data)
} }
CoglAtlas * CoglAtlas *
_cogl_atlas_new (CoglAtlasUpdatePositionCallback update_position_cb) _cogl_atlas_new (CoglPixelFormat texture_format,
CoglAtlasFlags flags,
CoglAtlasUpdatePositionCallback update_position_cb)
{ {
CoglAtlas *atlas = g_new (CoglAtlas, 1); CoglAtlas *atlas = g_new (CoglAtlas, 1);
atlas->update_position_cb = update_position_cb; atlas->update_position_cb = update_position_cb;
atlas->map = NULL; atlas->map = NULL;
atlas->texture = NULL; atlas->texture = NULL;
atlas->flags = flags;
atlas->texture_format = texture_format;
_cogl_callback_list_init (&atlas->reorganize_callbacks); _cogl_callback_list_init (&atlas->reorganize_callbacks);
return atlas; return atlas;
@ -244,6 +248,17 @@ _cogl_atlas_migrate (CoglAtlas *atlas,
unsigned int i; unsigned int i;
CoglAtlasBlitData blit_data; CoglAtlasBlitData blit_data;
/* If the 'disable migrate' flag is set then we won't actually copy
the textures to their new location. Instead we'll just invoke the
callback to update the position */
if ((atlas->flags & COGL_ATLAS_DISABLE_MIGRATION))
for (i = 0; i < n_textures; i++)
/* Update the texture position */
atlas->update_position_cb (textures[i].user_data,
new_texture,
&textures[i].new_position);
else
{
_cogl_atlas_blit_begin (&blit_data, new_texture, old_texture); _cogl_atlas_blit_begin (&blit_data, new_texture, old_texture);
for (i = 0; i < n_textures; i++) for (i = 0; i < n_textures; i++)
@ -251,7 +266,6 @@ _cogl_atlas_migrate (CoglAtlas *atlas,
/* Skip the texture that is being added because it doesn't contain /* Skip the texture that is being added because it doesn't contain
any data yet */ any data yet */
if (textures[i].user_data != skip_user_data) if (textures[i].user_data != skip_user_data)
{
_cogl_atlas_blit (&blit_data, _cogl_atlas_blit (&blit_data,
textures[i].old_position.x, textures[i].old_position.x,
textures[i].old_position.y, textures[i].old_position.y,
@ -259,7 +273,7 @@ _cogl_atlas_migrate (CoglAtlas *atlas,
textures[i].new_position.y, textures[i].new_position.y,
textures[i].new_position.width, textures[i].new_position.width,
textures[i].new_position.height); textures[i].new_position.height);
}
/* Update the texture position */ /* Update the texture position */
atlas->update_position_cb (textures[i].user_data, atlas->update_position_cb (textures[i].user_data,
new_texture, new_texture,
@ -267,6 +281,7 @@ _cogl_atlas_migrate (CoglAtlas *atlas,
} }
_cogl_atlas_blit_end (&blit_data); _cogl_atlas_blit_end (&blit_data);
}
} }
typedef struct _CoglAtlasGetRectanglesData typedef struct _CoglAtlasGetRectanglesData
@ -347,6 +362,40 @@ _cogl_atlas_create_map (unsigned int map_width,
return NULL; return NULL;
} }
static CoglHandle
_cogl_atlas_create_texture (CoglAtlas *atlas,
int width,
int height)
{
CoglHandle tex;
if ((atlas->flags & COGL_ATLAS_CLEAR_TEXTURE))
{
guint8 *clear_data;
CoglBitmap *clear_bmp;
int bpp = _cogl_get_format_bpp (atlas->texture_format);
/* Create a buffer of zeroes to initially clear the texture */
clear_data = g_malloc0 (width * height * bpp);
clear_bmp = _cogl_bitmap_new_from_data (clear_data,
atlas->texture_format,
width,
height,
width * bpp,
(CoglBitmapDestroyNotify) g_free,
NULL);
tex = _cogl_texture_2d_new_from_bitmap (clear_bmp, COGL_TEXTURE_NONE,
atlas->texture_format);
cogl_object_unref (clear_bmp);
}
else
tex = _cogl_texture_2d_new_with_size (width, height, COGL_TEXTURE_NONE,
atlas->texture_format);
return tex;
}
static int static int
_cogl_atlas_compare_size_cb (const void *a, _cogl_atlas_compare_size_cb (const void *a,
const void *b) const void *b)
@ -464,11 +513,10 @@ _cogl_atlas_reserve_space (CoglAtlas *atlas,
ret = FALSE; ret = FALSE;
} }
/* We need to migrate the existing textures into a new texture */ /* We need to migrate the existing textures into a new texture */
else if ((new_tex = _cogl_texture_2d_new_with_size else if ((new_tex = _cogl_atlas_create_texture
(_cogl_rectangle_map_get_width (new_map), (atlas,
_cogl_rectangle_map_get_height (new_map), _cogl_rectangle_map_get_width (new_map),
COGL_TEXTURE_NONE, _cogl_rectangle_map_get_height (new_map))) == COGL_INVALID_HANDLE)
COGL_PIXEL_FORMAT_RGBA_8888)) == COGL_INVALID_HANDLE)
{ {
COGL_NOTE (ATLAS, "Could not create a CoglTexture2D"); COGL_NOTE (ATLAS, "Could not create a CoglTexture2D");
_cogl_rectangle_map_free (new_map); _cogl_rectangle_map_free (new_map);

View File

@ -32,6 +32,12 @@ typedef void
CoglHandle new_texture, CoglHandle new_texture,
const CoglRectangleMapEntry *rect); const CoglRectangleMapEntry *rect);
typedef enum
{
COGL_ATLAS_CLEAR_TEXTURE = (1 << 0),
COGL_ATLAS_DISABLE_MIGRATION = (1 << 1)
} CoglAtlasFlags;
typedef struct _CoglAtlas CoglAtlas; typedef struct _CoglAtlas CoglAtlas;
struct _CoglAtlas struct _CoglAtlas
@ -39,6 +45,8 @@ struct _CoglAtlas
CoglRectangleMap *map; CoglRectangleMap *map;
CoglHandle texture; CoglHandle texture;
CoglPixelFormat texture_format;
CoglAtlasFlags flags;
CoglAtlasUpdatePositionCallback update_position_cb; CoglAtlasUpdatePositionCallback update_position_cb;
@ -46,7 +54,9 @@ struct _CoglAtlas
}; };
CoglAtlas * CoglAtlas *
_cogl_atlas_new (CoglAtlasUpdatePositionCallback update_position_cb); _cogl_atlas_new (CoglPixelFormat texture_format,
CoglAtlasFlags flags,
CoglAtlasUpdatePositionCallback update_position_cb);
gboolean gboolean
_cogl_atlas_reserve_space (CoglAtlas *atlas, _cogl_atlas_reserve_space (CoglAtlas *atlas,