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:
parent
9b2f8179f0
commit
047227fbd7
@ -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,
|
||||||
|
@ -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,29 +248,40 @@ _cogl_atlas_migrate (CoglAtlas *atlas,
|
|||||||
unsigned int i;
|
unsigned int i;
|
||||||
CoglAtlasBlitData blit_data;
|
CoglAtlasBlitData blit_data;
|
||||||
|
|
||||||
_cogl_atlas_blit_begin (&blit_data, new_texture, old_texture);
|
/* 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
|
||||||
for (i = 0; i < n_textures; i++)
|
callback to update the position */
|
||||||
{
|
if ((atlas->flags & COGL_ATLAS_DISABLE_MIGRATION))
|
||||||
/* Skip the texture that is being added because it doesn't contain
|
for (i = 0; i < n_textures; i++)
|
||||||
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 */
|
/* Update the texture position */
|
||||||
atlas->update_position_cb (textures[i].user_data,
|
atlas->update_position_cb (textures[i].user_data,
|
||||||
new_texture,
|
new_texture,
|
||||||
&textures[i].new_position);
|
&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
|
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);
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user