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 b2f2e69264
commit bbac324356
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)
{
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_texture_reorganize_cb,

View File

@ -199,13 +199,17 @@ _cogl_atlas_blit_end (CoglAtlasBlitData *data)
}
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);
atlas->update_position_cb = update_position_cb;
atlas->map = NULL;
atlas->texture = NULL;
atlas->flags = flags;
atlas->texture_format = texture_format;
_cogl_callback_list_init (&atlas->reorganize_callbacks);
return atlas;
@ -244,29 +248,40 @@ _cogl_atlas_migrate (CoglAtlas *atlas,
unsigned int i;
CoglAtlasBlitData blit_data;
_cogl_atlas_blit_begin (&blit_data, new_texture, old_texture);
for (i = 0; i < n_textures; i++)
{
/* Skip the texture that is being added because it doesn't contain
any data yet */
if (textures[i].user_data != skip_user_data)
{
_cogl_atlas_blit (&blit_data,
textures[i].old_position.x,
textures[i].old_position.y,
textures[i].new_position.x,
textures[i].new_position.y,
textures[i].new_position.width,
textures[i].new_position.height);
}
/* 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_end (&blit_data);
for (i = 0; i < n_textures; i++)
{
/* Skip the texture that is being added because it doesn't contain
any data yet */
if (textures[i].user_data != skip_user_data)
_cogl_atlas_blit (&blit_data,
textures[i].old_position.x,
textures[i].old_position.y,
textures[i].new_position.x,
textures[i].new_position.y,
textures[i].new_position.width,
textures[i].new_position.height);
/* Update the texture position */
atlas->update_position_cb (textures[i].user_data,
new_texture,
&textures[i].new_position);
}
_cogl_atlas_blit_end (&blit_data);
}
}
typedef struct _CoglAtlasGetRectanglesData
@ -347,6 +362,40 @@ _cogl_atlas_create_map (unsigned int map_width,
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
_cogl_atlas_compare_size_cb (const void *a,
const void *b)
@ -464,11 +513,10 @@ _cogl_atlas_reserve_space (CoglAtlas *atlas,
ret = FALSE;
}
/* We need to migrate the existing textures into a new texture */
else if ((new_tex = _cogl_texture_2d_new_with_size
(_cogl_rectangle_map_get_width (new_map),
_cogl_rectangle_map_get_height (new_map),
COGL_TEXTURE_NONE,
COGL_PIXEL_FORMAT_RGBA_8888)) == COGL_INVALID_HANDLE)
else if ((new_tex = _cogl_atlas_create_texture
(atlas,
_cogl_rectangle_map_get_width (new_map),
_cogl_rectangle_map_get_height (new_map))) == COGL_INVALID_HANDLE)
{
COGL_NOTE (ATLAS, "Could not create a CoglTexture2D");
_cogl_rectangle_map_free (new_map);

View File

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