mirror of
https://github.com/brl/mutter.git
synced 2024-11-22 16:10:41 -05:00
cogl-atlas: Rename to CoglRectangleMap
This simply renames CoglAtlas to CoglRectangleMap without making any functional changes. The old 'CoglAtlas' is just a data structure for managing unused areas of a rectangle and it doesn't neccessarily have to be used for an atlas so it wasn't a very good name.
This commit is contained in:
parent
1e45428483
commit
4989000f55
@ -144,8 +144,8 @@ cogl_sources_c = \
|
|||||||
$(srcdir)/cogl-texture-3d.c \
|
$(srcdir)/cogl-texture-3d.c \
|
||||||
$(srcdir)/cogl-texture-rectangle-private.h \
|
$(srcdir)/cogl-texture-rectangle-private.h \
|
||||||
$(srcdir)/cogl-texture-rectangle.c \
|
$(srcdir)/cogl-texture-rectangle.c \
|
||||||
$(srcdir)/cogl-atlas.h \
|
$(srcdir)/cogl-rectangle-map.h \
|
||||||
$(srcdir)/cogl-atlas.c \
|
$(srcdir)/cogl-rectangle-map.c \
|
||||||
$(srcdir)/cogl-atlas-texture-private.h \
|
$(srcdir)/cogl-atlas-texture-private.h \
|
||||||
$(srcdir)/cogl-atlas-texture.c \
|
$(srcdir)/cogl-atlas-texture.c \
|
||||||
$(srcdir)/cogl-spans.h \
|
$(srcdir)/cogl-spans.h \
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
#include "cogl-handle.h"
|
#include "cogl-handle.h"
|
||||||
#include "cogl-texture-private.h"
|
#include "cogl-texture-private.h"
|
||||||
#include "cogl-atlas.h"
|
#include "cogl-rectangle-map.h"
|
||||||
|
|
||||||
#define COGL_ATLAS_TEXTURE(tex) ((CoglAtlasTexture *) tex)
|
#define COGL_ATLAS_TEXTURE(tex) ((CoglAtlasTexture *) tex)
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ struct _CoglAtlasTexture
|
|||||||
|
|
||||||
/* The rectangle that was used to add this texture to the
|
/* The rectangle that was used to add this texture to the
|
||||||
atlas. This includes the 1-pixel border */
|
atlas. This includes the 1-pixel border */
|
||||||
CoglAtlasRectangle rectangle;
|
CoglRectangleMapEntry rectangle;
|
||||||
|
|
||||||
/* The texture might need to be migrated out in which case this will
|
/* The texture might need to be migrated out in which case this will
|
||||||
be set to TRUE and sub_texture will actually be a real texture */
|
be set to TRUE and sub_texture will actually be a real texture */
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
#include "cogl-context.h"
|
#include "cogl-context.h"
|
||||||
#include "cogl-handle.h"
|
#include "cogl-handle.h"
|
||||||
#include "cogl-texture-driver.h"
|
#include "cogl-texture-driver.h"
|
||||||
#include "cogl-atlas.h"
|
#include "cogl-rectangle-map.h"
|
||||||
#include "cogl-journal-private.h"
|
#include "cogl-journal-private.h"
|
||||||
#include "cogl-material-opengl-private.h"
|
#include "cogl-material-opengl-private.h"
|
||||||
|
|
||||||
@ -254,18 +254,18 @@ _cogl_atlas_texture_remove_from_atlas (CoglAtlasTexture *atlas_tex)
|
|||||||
{
|
{
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
_cogl_atlas_remove_rectangle (ctx->atlas, &atlas_tex->rectangle);
|
_cogl_rectangle_map_remove (ctx->rectangle_map, &atlas_tex->rectangle);
|
||||||
|
|
||||||
COGL_NOTE (ATLAS, "Removed rectangle sized %ix%i",
|
COGL_NOTE (ATLAS, "Removed rectangle sized %ix%i",
|
||||||
atlas_tex->rectangle.width,
|
atlas_tex->rectangle.width,
|
||||||
atlas_tex->rectangle.height);
|
atlas_tex->rectangle.height);
|
||||||
COGL_NOTE (ATLAS, "Atlas is %ix%i, has %i textures and is %i%% waste",
|
COGL_NOTE (ATLAS, "Atlas is %ix%i, has %i textures and is %i%% waste",
|
||||||
_cogl_atlas_get_width (ctx->atlas),
|
_cogl_rectangle_map_get_width (ctx->rectangle_map),
|
||||||
_cogl_atlas_get_height (ctx->atlas),
|
_cogl_rectangle_map_get_height (ctx->rectangle_map),
|
||||||
_cogl_atlas_get_n_rectangles (ctx->atlas),
|
_cogl_rectangle_map_get_n_rectangles (ctx->rectangle_map),
|
||||||
_cogl_atlas_get_remaining_space (ctx->atlas) * 100 /
|
_cogl_rectangle_map_get_remaining_space (ctx->rectangle_map) *
|
||||||
(_cogl_atlas_get_width (ctx->atlas) *
|
100 / (_cogl_rectangle_map_get_width (ctx->rectangle_map) *
|
||||||
_cogl_atlas_get_height (ctx->atlas)));
|
_cogl_rectangle_map_get_height (ctx->rectangle_map)));
|
||||||
|
|
||||||
atlas_tex->in_atlas = FALSE;
|
atlas_tex->in_atlas = FALSE;
|
||||||
}
|
}
|
||||||
@ -599,7 +599,7 @@ _cogl_atlas_texture_get_height (CoglTexture *tex)
|
|||||||
|
|
||||||
static CoglHandle
|
static CoglHandle
|
||||||
_cogl_atlas_texture_create_sub_texture (CoglHandle full_texture,
|
_cogl_atlas_texture_create_sub_texture (CoglHandle full_texture,
|
||||||
const CoglAtlasRectangle *rectangle)
|
const CoglRectangleMapEntry *rectangle)
|
||||||
{
|
{
|
||||||
/* Create a subtexture for the given rectangle not including the
|
/* Create a subtexture for the given rectangle not including the
|
||||||
1-pixel border */
|
1-pixel border */
|
||||||
@ -615,7 +615,7 @@ typedef struct _CoglAtlasTextureRepositionData
|
|||||||
/* The current texture which already has a position */
|
/* The current texture which already has a position */
|
||||||
CoglAtlasTexture *texture;
|
CoglAtlasTexture *texture;
|
||||||
/* The new position of the texture */
|
/* The new position of the texture */
|
||||||
CoglAtlasRectangle new_position;
|
CoglRectangleMapEntry new_position;
|
||||||
} CoglAtlasTextureRepositionData;
|
} CoglAtlasTextureRepositionData;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -679,30 +679,30 @@ typedef struct _CoglAtlasTextureGetRectanglesData
|
|||||||
} CoglAtlasTextureGetRectanglesData;
|
} CoglAtlasTextureGetRectanglesData;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cogl_atlas_texture_get_rectangles_cb (const CoglAtlasRectangle *rectangle,
|
_cogl_atlas_texture_get_rectangles_cb (const CoglRectangleMapEntry *rectangle,
|
||||||
gpointer rectangle_data,
|
gpointer rect_data,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
CoglAtlasTextureGetRectanglesData *data = user_data;
|
CoglAtlasTextureGetRectanglesData *data = user_data;
|
||||||
|
|
||||||
data->textures[data->n_textures++].texture = rectangle_data;
|
data->textures[data->n_textures++].texture = rect_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cogl_atlas_texture_get_next_size (unsigned int *atlas_width,
|
_cogl_atlas_texture_get_next_size (unsigned int *map_width,
|
||||||
unsigned int *atlas_height)
|
unsigned int *map_height)
|
||||||
{
|
{
|
||||||
/* Double the size of the texture by increasing whichever dimension
|
/* Double the size of the texture by increasing whichever dimension
|
||||||
is smaller */
|
is smaller */
|
||||||
if (*atlas_width < *atlas_height)
|
if (*map_width < *map_height)
|
||||||
*atlas_width <<= 1;
|
*map_width <<= 1;
|
||||||
else
|
else
|
||||||
*atlas_height <<= 1;
|
*map_height <<= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CoglAtlas *
|
static CoglRectangleMap *
|
||||||
_cogl_atlas_texture_create_atlas (unsigned int atlas_width,
|
_cogl_atlas_texture_create_map (unsigned int map_width,
|
||||||
unsigned int atlas_height,
|
unsigned int map_height,
|
||||||
unsigned int n_textures,
|
unsigned int n_textures,
|
||||||
CoglAtlasTextureRepositionData *textures)
|
CoglAtlasTextureRepositionData *textures)
|
||||||
{
|
{
|
||||||
@ -717,14 +717,16 @@ _cogl_atlas_texture_create_atlas (unsigned int atlas_width,
|
|||||||
|
|
||||||
/* Keep trying increasingly larger atlases until we can fit all of
|
/* Keep trying increasingly larger atlases until we can fit all of
|
||||||
the textures */
|
the textures */
|
||||||
while (atlas_width < max_texture_size && atlas_height < max_texture_size)
|
while (map_width < max_texture_size && map_height < max_texture_size)
|
||||||
{
|
{
|
||||||
CoglAtlas *new_atlas = _cogl_atlas_new (atlas_width, atlas_height, NULL);
|
CoglRectangleMap *new_atlas = _cogl_rectangle_map_new (map_width,
|
||||||
|
map_height,
|
||||||
|
NULL);
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
/* Add all of the textures and keep track of the new position */
|
/* Add all of the textures and keep track of the new position */
|
||||||
for (i = 0; i < n_textures; i++)
|
for (i = 0; i < n_textures; i++)
|
||||||
if (!_cogl_atlas_add_rectangle (new_atlas,
|
if (!_cogl_rectangle_map_add (new_atlas,
|
||||||
textures[i].texture->rectangle.width,
|
textures[i].texture->rectangle.width,
|
||||||
textures[i].texture->rectangle.height,
|
textures[i].texture->rectangle.height,
|
||||||
textures[i].texture,
|
textures[i].texture,
|
||||||
@ -736,8 +738,8 @@ _cogl_atlas_texture_create_atlas (unsigned int atlas_width,
|
|||||||
if (i >= n_textures)
|
if (i >= n_textures)
|
||||||
return new_atlas;
|
return new_atlas;
|
||||||
|
|
||||||
_cogl_atlas_free (new_atlas);
|
_cogl_rectangle_map_free (new_atlas);
|
||||||
_cogl_atlas_texture_get_next_size (&atlas_width, &atlas_height);
|
_cogl_atlas_texture_get_next_size (&map_width, &map_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we get here then there's no atlas that can accommodate all of
|
/* If we get here then there's no atlas that can accommodate all of
|
||||||
@ -766,25 +768,26 @@ _cogl_atlas_texture_reserve_space (CoglAtlasTexture *new_sub_tex,
|
|||||||
unsigned int height)
|
unsigned int height)
|
||||||
{
|
{
|
||||||
CoglAtlasTextureGetRectanglesData data;
|
CoglAtlasTextureGetRectanglesData data;
|
||||||
CoglAtlas *new_atlas;
|
CoglRectangleMap *new_map;
|
||||||
CoglHandle new_tex;
|
CoglHandle new_tex;
|
||||||
unsigned int atlas_width, atlas_height;
|
unsigned int map_width, map_height;
|
||||||
gboolean ret;
|
gboolean ret;
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, FALSE);
|
_COGL_GET_CONTEXT (ctx, FALSE);
|
||||||
|
|
||||||
/* Check if we can fit the rectangle into the existing atlas */
|
/* Check if we can fit the rectangle into the existing atlas */
|
||||||
if (ctx->atlas && _cogl_atlas_add_rectangle (ctx->atlas, width, height,
|
if (ctx->rectangle_map &&
|
||||||
|
_cogl_rectangle_map_add (ctx->rectangle_map, width, height,
|
||||||
new_sub_tex,
|
new_sub_tex,
|
||||||
&new_sub_tex->rectangle))
|
&new_sub_tex->rectangle))
|
||||||
{
|
{
|
||||||
COGL_NOTE (ATLAS, "Atlas is %ix%i, has %i textures and is %i%% waste",
|
COGL_NOTE (ATLAS, "Atlas is %ix%i, has %i textures and is %i%% waste",
|
||||||
_cogl_atlas_get_width (ctx->atlas),
|
_cogl_rectangle_map_get_width (ctx->rectangle_map),
|
||||||
_cogl_atlas_get_height (ctx->atlas),
|
_cogl_rectangle_map_get_height (ctx->rectangle_map),
|
||||||
_cogl_atlas_get_n_rectangles (ctx->atlas),
|
_cogl_rectangle_map_get_n_rectangles (ctx->rectangle_map),
|
||||||
_cogl_atlas_get_remaining_space (ctx->atlas) * 100 /
|
_cogl_rectangle_map_get_remaining_space (ctx->rectangle_map) *
|
||||||
(_cogl_atlas_get_width (ctx->atlas) *
|
100 / (_cogl_rectangle_map_get_width (ctx->rectangle_map) *
|
||||||
_cogl_atlas_get_height (ctx->atlas)));
|
_cogl_rectangle_map_get_height (ctx->rectangle_map)));
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -792,14 +795,16 @@ _cogl_atlas_texture_reserve_space (CoglAtlasTexture *new_sub_tex,
|
|||||||
/* We need to reorganise the atlas so we'll get an array of all the
|
/* We need to reorganise the atlas so we'll get an array of all the
|
||||||
textures currently in the atlas. */
|
textures currently in the atlas. */
|
||||||
data.n_textures = 0;
|
data.n_textures = 0;
|
||||||
if (ctx->atlas == NULL)
|
if (ctx->rectangle_map == NULL)
|
||||||
data.textures = g_malloc (sizeof (CoglAtlasTextureRepositionData));
|
data.textures = g_malloc (sizeof (CoglAtlasTextureRepositionData));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
data.textures =
|
unsigned int n_rectangles =
|
||||||
g_malloc (sizeof (CoglAtlasTextureRepositionData) *
|
_cogl_rectangle_map_get_n_rectangles (ctx->rectangle_map);
|
||||||
(_cogl_atlas_get_n_rectangles (ctx->atlas) + 1));
|
data.textures = g_malloc (sizeof (CoglAtlasTextureRepositionData) *
|
||||||
_cogl_atlas_foreach (ctx->atlas, _cogl_atlas_texture_get_rectangles_cb,
|
(n_rectangles + 1));
|
||||||
|
_cogl_rectangle_map_foreach (ctx->rectangle_map,
|
||||||
|
_cogl_atlas_texture_get_rectangles_cb,
|
||||||
&data);
|
&data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -815,59 +820,61 @@ _cogl_atlas_texture_reserve_space (CoglAtlasTexture *new_sub_tex,
|
|||||||
_cogl_atlas_texture_compare_size_cb);
|
_cogl_atlas_texture_compare_size_cb);
|
||||||
|
|
||||||
/* Try to create a new atlas that can contain all of the textures */
|
/* Try to create a new atlas that can contain all of the textures */
|
||||||
if (ctx->atlas)
|
if (ctx->rectangle_map)
|
||||||
{
|
{
|
||||||
atlas_width = _cogl_atlas_get_width (ctx->atlas);
|
map_width = _cogl_rectangle_map_get_width (ctx->rectangle_map);
|
||||||
atlas_height = _cogl_atlas_get_height (ctx->atlas);
|
map_height = _cogl_rectangle_map_get_height (ctx->rectangle_map);
|
||||||
|
|
||||||
/* If there is enough space in the existing for the new
|
/* If there is enough space in the existing for the new
|
||||||
rectangle in the existing atlas we'll start with the same
|
rectangle in the existing atlas we'll start with the same
|
||||||
size, otherwise we'll immediately double it */
|
size, otherwise we'll immediately double it */
|
||||||
if (_cogl_atlas_get_remaining_space (ctx->atlas) < width * height)
|
if (_cogl_rectangle_map_get_remaining_space (ctx->rectangle_map) <
|
||||||
_cogl_atlas_texture_get_next_size (&atlas_width, &atlas_height);
|
width * height)
|
||||||
|
_cogl_atlas_texture_get_next_size (&map_width, &map_height);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Start with an initial size of 256x256 */
|
/* Start with an initial size of 256x256 */
|
||||||
atlas_width = 256;
|
map_width = 256;
|
||||||
atlas_height = 256;
|
map_height = 256;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_atlas = _cogl_atlas_texture_create_atlas (atlas_width, atlas_height,
|
new_map = _cogl_atlas_texture_create_map (map_width, map_height,
|
||||||
data.n_textures, data.textures);
|
data.n_textures, data.textures);
|
||||||
|
map_width = _cogl_rectangle_map_get_width (new_map);
|
||||||
|
map_height = _cogl_rectangle_map_get_height (new_map);
|
||||||
|
|
||||||
/* If we can't create an atlas with the texture then give up */
|
/* If we can't create a map with the texture then give up */
|
||||||
if (new_atlas == NULL)
|
if (new_map == NULL)
|
||||||
{
|
{
|
||||||
COGL_NOTE (ATLAS, "Could not fit texture in the atlas");
|
COGL_NOTE (ATLAS, "Could not fit texture in the 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 =
|
else if ((new_tex =
|
||||||
_cogl_texture_2d_new_with_size (_cogl_atlas_get_width (new_atlas),
|
_cogl_texture_2d_new_with_size (map_width, map_height,
|
||||||
_cogl_atlas_get_height (new_atlas),
|
|
||||||
COGL_TEXTURE_NONE,
|
COGL_TEXTURE_NONE,
|
||||||
COGL_PIXEL_FORMAT_RGBA_8888)) ==
|
COGL_PIXEL_FORMAT_RGBA_8888)) ==
|
||||||
COGL_INVALID_HANDLE)
|
COGL_INVALID_HANDLE)
|
||||||
{
|
{
|
||||||
COGL_NOTE (ATLAS, "Could not create a CoglTexture2D");
|
COGL_NOTE (ATLAS, "Could not create a CoglTexture2D");
|
||||||
_cogl_atlas_free (new_atlas);
|
_cogl_rectangle_map_free (new_map);
|
||||||
ret = FALSE;
|
ret = FALSE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
COGL_NOTE (ATLAS,
|
COGL_NOTE (ATLAS,
|
||||||
"Atlas %s with size %ix%i",
|
"Atlas %s with size %ix%i",
|
||||||
ctx->atlas == NULL ||
|
ctx->rectangle_map == NULL ||
|
||||||
_cogl_atlas_get_width (ctx->atlas) !=
|
_cogl_rectangle_map_get_width (ctx->rectangle_map) !=
|
||||||
_cogl_atlas_get_width (new_atlas) ||
|
_cogl_rectangle_map_get_width (new_map) ||
|
||||||
_cogl_atlas_get_height (ctx->atlas) !=
|
_cogl_rectangle_map_get_height (ctx->rectangle_map) !=
|
||||||
_cogl_atlas_get_height (new_atlas) ?
|
_cogl_rectangle_map_get_height (new_map) ?
|
||||||
"resized" : "reorganized",
|
"resized" : "reorganized",
|
||||||
_cogl_atlas_get_width (new_atlas),
|
_cogl_rectangle_map_get_width (new_map),
|
||||||
_cogl_atlas_get_height (new_atlas));
|
_cogl_rectangle_map_get_height (new_map));
|
||||||
|
|
||||||
if (ctx->atlas)
|
if (ctx->rectangle_map)
|
||||||
{
|
{
|
||||||
/* Move all the textures to the right position in the new
|
/* Move all the textures to the right position in the new
|
||||||
texture. This will also update the texture's rectangle */
|
texture. This will also update the texture's rectangle */
|
||||||
@ -876,7 +883,7 @@ _cogl_atlas_texture_reserve_space (CoglAtlasTexture *new_sub_tex,
|
|||||||
ctx->atlas_texture,
|
ctx->atlas_texture,
|
||||||
new_tex,
|
new_tex,
|
||||||
new_sub_tex);
|
new_sub_tex);
|
||||||
_cogl_atlas_free (ctx->atlas);
|
_cogl_rectangle_map_free (ctx->rectangle_map);
|
||||||
cogl_handle_unref (ctx->atlas_texture);
|
cogl_handle_unref (ctx->atlas_texture);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -884,16 +891,16 @@ _cogl_atlas_texture_reserve_space (CoglAtlasTexture *new_sub_tex,
|
|||||||
update the rectangle from its new position */
|
update the rectangle from its new position */
|
||||||
data.textures[0].texture->rectangle = data.textures[0].new_position;
|
data.textures[0].texture->rectangle = data.textures[0].new_position;
|
||||||
|
|
||||||
ctx->atlas = new_atlas;
|
ctx->rectangle_map = new_map;
|
||||||
ctx->atlas_texture = new_tex;
|
ctx->atlas_texture = new_tex;
|
||||||
|
|
||||||
COGL_NOTE (ATLAS, "Atlas is %ix%i, has %i textures and is %i%% waste",
|
COGL_NOTE (ATLAS, "Atlas is %ix%i, has %i textures and is %i%% waste",
|
||||||
_cogl_atlas_get_width (ctx->atlas),
|
_cogl_rectangle_map_get_width (ctx->rectangle_map),
|
||||||
_cogl_atlas_get_height (ctx->atlas),
|
_cogl_rectangle_map_get_height (ctx->rectangle_map),
|
||||||
_cogl_atlas_get_n_rectangles (ctx->atlas),
|
_cogl_rectangle_map_get_n_rectangles (ctx->rectangle_map),
|
||||||
_cogl_atlas_get_remaining_space (ctx->atlas) * 100 /
|
_cogl_rectangle_map_get_remaining_space (ctx->rectangle_map) *
|
||||||
(_cogl_atlas_get_width (ctx->atlas) *
|
100 / (_cogl_rectangle_map_get_width (ctx->rectangle_map) *
|
||||||
_cogl_atlas_get_height (ctx->atlas)));
|
_cogl_rectangle_map_get_height (ctx->rectangle_map)));
|
||||||
|
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
}
|
}
|
||||||
@ -1003,7 +1010,7 @@ _cogl_atlas_texture_new_from_bitmap (CoglBitmap *bmp,
|
|||||||
|
|
||||||
if (dst_bmp == NULL)
|
if (dst_bmp == NULL)
|
||||||
{
|
{
|
||||||
_cogl_atlas_remove_rectangle (ctx->atlas, &atlas_tex->rectangle);
|
_cogl_rectangle_map_remove (ctx->rectangle_map, &atlas_tex->rectangle);
|
||||||
g_free (atlas_tex);
|
g_free (atlas_tex);
|
||||||
return COGL_INVALID_HANDLE;
|
return COGL_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
* Cogl
|
|
||||||
*
|
|
||||||
* An object oriented GL/GLES Abstraction/Utility Layer
|
|
||||||
*
|
|
||||||
* Copyright (C) 2009 Intel Corporation.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __COGL_ATLAS_H
|
|
||||||
#define __COGL_ATLAS_H
|
|
||||||
|
|
||||||
#include <glib.h>
|
|
||||||
|
|
||||||
typedef struct _CoglAtlas CoglAtlas;
|
|
||||||
typedef struct _CoglAtlasRectangle CoglAtlasRectangle;
|
|
||||||
|
|
||||||
typedef void (* CoglAtlasCallback) (const CoglAtlasRectangle *rectangle,
|
|
||||||
gpointer rectangle_data,
|
|
||||||
gpointer user_data);
|
|
||||||
|
|
||||||
struct _CoglAtlasRectangle
|
|
||||||
{
|
|
||||||
unsigned int x, y;
|
|
||||||
unsigned int width, height;
|
|
||||||
};
|
|
||||||
|
|
||||||
CoglAtlas *
|
|
||||||
_cogl_atlas_new (unsigned int width,
|
|
||||||
unsigned int height,
|
|
||||||
GDestroyNotify value_destroy_func);
|
|
||||||
|
|
||||||
gboolean
|
|
||||||
_cogl_atlas_add_rectangle (CoglAtlas *atlas,
|
|
||||||
unsigned int width,
|
|
||||||
unsigned int height,
|
|
||||||
gpointer data,
|
|
||||||
CoglAtlasRectangle *rectangle);
|
|
||||||
|
|
||||||
void
|
|
||||||
_cogl_atlas_remove_rectangle (CoglAtlas *atlas,
|
|
||||||
const CoglAtlasRectangle *rectangle);
|
|
||||||
|
|
||||||
unsigned int
|
|
||||||
_cogl_atlas_get_width (CoglAtlas *atlas);
|
|
||||||
|
|
||||||
unsigned int
|
|
||||||
_cogl_atlas_get_height (CoglAtlas *atlas);
|
|
||||||
|
|
||||||
unsigned int
|
|
||||||
_cogl_atlas_get_remaining_space (CoglAtlas *atlas);
|
|
||||||
|
|
||||||
unsigned int
|
|
||||||
_cogl_atlas_get_n_rectangles (CoglAtlas *atlas);
|
|
||||||
|
|
||||||
void
|
|
||||||
_cogl_atlas_foreach (CoglAtlas *atlas,
|
|
||||||
CoglAtlasCallback callback,
|
|
||||||
gpointer data);
|
|
||||||
|
|
||||||
void
|
|
||||||
_cogl_atlas_free (CoglAtlas *atlas);
|
|
||||||
|
|
||||||
#endif /* __COGL_ATLAS_H */
|
|
@ -214,7 +214,7 @@ cogl_create_context (void)
|
|||||||
_cogl_enable (enable_flags);
|
_cogl_enable (enable_flags);
|
||||||
_cogl_flush_face_winding ();
|
_cogl_flush_face_winding ();
|
||||||
|
|
||||||
_context->atlas = NULL;
|
_context->rectangle_map = NULL;
|
||||||
_context->atlas_texture = COGL_INVALID_HANDLE;
|
_context->atlas_texture = COGL_INVALID_HANDLE;
|
||||||
|
|
||||||
/* As far as I can tell, GL_POINT_SPRITE doesn't have any effect
|
/* As far as I can tell, GL_POINT_SPRITE doesn't have any effect
|
||||||
@ -273,8 +273,9 @@ _cogl_destroy_context (void)
|
|||||||
if (_context->default_layer_0)
|
if (_context->default_layer_0)
|
||||||
cogl_handle_unref (_context->default_layer_0);
|
cogl_handle_unref (_context->default_layer_0);
|
||||||
|
|
||||||
if (_context->atlas)
|
if (_context->rectangle_map)
|
||||||
_cogl_atlas_free (_context->atlas);
|
_cogl_rectangle_map_free (_context->rectangle_map);
|
||||||
|
|
||||||
if (_context->atlas_texture)
|
if (_context->atlas_texture)
|
||||||
cogl_handle_unref (_context->atlas_texture);
|
cogl_handle_unref (_context->atlas_texture);
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
#include "cogl-clip-stack.h"
|
#include "cogl-clip-stack.h"
|
||||||
#include "cogl-matrix-stack.h"
|
#include "cogl-matrix-stack.h"
|
||||||
#include "cogl-material-private.h"
|
#include "cogl-material-private.h"
|
||||||
#include "cogl-atlas.h"
|
#include "cogl-rectangle-map.h"
|
||||||
#include "cogl-buffer-private.h"
|
#include "cogl-buffer-private.h"
|
||||||
#include "cogl-bitmask.h"
|
#include "cogl-bitmask.h"
|
||||||
|
|
||||||
@ -143,7 +143,7 @@ typedef struct
|
|||||||
|
|
||||||
CoglMaterial *texture_download_material;
|
CoglMaterial *texture_download_material;
|
||||||
|
|
||||||
CoglAtlas *atlas;
|
CoglRectangleMap *rectangle_map;
|
||||||
CoglHandle atlas_texture;
|
CoglHandle atlas_texture;
|
||||||
|
|
||||||
/* This debugging variable is used to pick a colour for visually
|
/* This debugging variable is used to pick a colour for visually
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
#include "cogl-atlas.h"
|
#include "cogl-rectangle-map.h"
|
||||||
#include "cogl-debug.h"
|
#include "cogl-debug.h"
|
||||||
|
|
||||||
/* Implements a data structure which keeps track of unused
|
/* Implements a data structure which keeps track of unused
|
||||||
@ -46,26 +46,26 @@
|
|||||||
the atlas */
|
the atlas */
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
|
|
||||||
static void _cogl_atlas_dump_image (CoglAtlas *atlas);
|
static void _cogl_rectangle_map_dump_image (CoglRectangleMap *map);
|
||||||
|
|
||||||
#endif /* COGL_ENABLE_DEBUG */
|
#endif /* COGL_ENABLE_DEBUG */
|
||||||
|
|
||||||
typedef struct _CoglAtlasNode CoglAtlasNode;
|
typedef struct _CoglRectangleMapNode CoglRectangleMapNode;
|
||||||
typedef struct _CoglAtlasStackEntry CoglAtlasStackEntry;
|
typedef struct _CoglRectangleMapStackEntry CoglRectangleMapStackEntry;
|
||||||
|
|
||||||
typedef void (* CoglAtlasInternalForeachCb) (CoglAtlasNode *node,
|
typedef void (* CoglRectangleMapInternalForeachCb) (CoglRectangleMapNode *node,
|
||||||
gpointer data);
|
void *data);
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
COGL_ATLAS_BRANCH,
|
COGL_RECTANGLE_MAP_BRANCH,
|
||||||
COGL_ATLAS_FILLED_LEAF,
|
COGL_RECTANGLE_MAP_FILLED_LEAF,
|
||||||
COGL_ATLAS_EMPTY_LEAF
|
COGL_RECTANGLE_MAP_EMPTY_LEAF
|
||||||
} CoglAtlasNodeType;
|
} CoglRectangleMapNodeType;
|
||||||
|
|
||||||
struct _CoglAtlas
|
struct _CoglRectangleMap
|
||||||
{
|
{
|
||||||
CoglAtlasNode *root;
|
CoglRectangleMapNode *root;
|
||||||
|
|
||||||
unsigned int space_remaining;
|
unsigned int space_remaining;
|
||||||
unsigned int n_rectangles;
|
unsigned int n_rectangles;
|
||||||
@ -73,80 +73,81 @@ struct _CoglAtlas
|
|||||||
GDestroyNotify value_destroy_func;
|
GDestroyNotify value_destroy_func;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _CoglAtlasNode
|
struct _CoglRectangleMapNode
|
||||||
{
|
{
|
||||||
CoglAtlasNodeType type;
|
CoglRectangleMapNodeType type;
|
||||||
|
|
||||||
CoglAtlasRectangle rectangle;
|
CoglRectangleMapEntry rectangle;
|
||||||
|
|
||||||
CoglAtlasNode *parent;
|
CoglRectangleMapNode *parent;
|
||||||
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
/* Fields used when this is a branch */
|
/* Fields used when this is a branch */
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
CoglAtlasNode *left;
|
CoglRectangleMapNode *left;
|
||||||
CoglAtlasNode *right;
|
CoglRectangleMapNode *right;
|
||||||
} branch;
|
} branch;
|
||||||
|
|
||||||
/* Field used when this is a filled leaf */
|
/* Field used when this is a filled leaf */
|
||||||
gpointer data;
|
void *data;
|
||||||
} d;
|
} d;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _CoglAtlasStackEntry
|
struct _CoglRectangleMapStackEntry
|
||||||
{
|
{
|
||||||
/* The node to search */
|
/* The node to search */
|
||||||
CoglAtlasNode *node;
|
CoglRectangleMapNode *node;
|
||||||
/* Index of next branch of this node to explore. Basically either 0
|
/* Index of next branch of this node to explore. Basically either 0
|
||||||
to go left or 1 to go right */
|
to go left or 1 to go right */
|
||||||
gboolean next_index;
|
gboolean next_index;
|
||||||
/* Next entry in the stack */
|
/* Next entry in the stack */
|
||||||
CoglAtlasStackEntry *next;
|
CoglRectangleMapStackEntry *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
static CoglAtlasNode *
|
static CoglRectangleMapNode *
|
||||||
_cogl_atlas_node_new (void)
|
_cogl_rectangle_map_node_new (void)
|
||||||
{
|
{
|
||||||
return g_slice_new (CoglAtlasNode);
|
return g_slice_new (CoglRectangleMapNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cogl_atlas_node_free (CoglAtlasNode *node)
|
_cogl_rectangle_map_node_free (CoglRectangleMapNode *node)
|
||||||
{
|
{
|
||||||
g_slice_free (CoglAtlasNode, node);
|
g_slice_free (CoglRectangleMapNode, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
CoglAtlas *
|
CoglRectangleMap *
|
||||||
_cogl_atlas_new (unsigned int width,
|
_cogl_rectangle_map_new (unsigned int width,
|
||||||
unsigned int height,
|
unsigned int height,
|
||||||
GDestroyNotify value_destroy_func)
|
GDestroyNotify value_destroy_func)
|
||||||
{
|
{
|
||||||
CoglAtlas *atlas = g_new (CoglAtlas, 1);
|
CoglRectangleMap *map = g_new (CoglRectangleMap, 1);
|
||||||
CoglAtlasNode *root = _cogl_atlas_node_new ();
|
CoglRectangleMapNode *root = _cogl_rectangle_map_node_new ();
|
||||||
|
|
||||||
root->type = COGL_ATLAS_EMPTY_LEAF;
|
root->type = COGL_RECTANGLE_MAP_EMPTY_LEAF;
|
||||||
root->parent = NULL;
|
root->parent = NULL;
|
||||||
root->rectangle.x = 0;
|
root->rectangle.x = 0;
|
||||||
root->rectangle.y = 0;
|
root->rectangle.y = 0;
|
||||||
root->rectangle.width = width;
|
root->rectangle.width = width;
|
||||||
root->rectangle.height = height;
|
root->rectangle.height = height;
|
||||||
|
|
||||||
atlas->root = root;
|
map->root = root;
|
||||||
atlas->space_remaining = width * height;
|
map->space_remaining = width * height;
|
||||||
atlas->n_rectangles = 0;
|
map->n_rectangles = 0;
|
||||||
atlas->value_destroy_func = value_destroy_func;
|
map->value_destroy_func = value_destroy_func;
|
||||||
|
|
||||||
return atlas;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CoglAtlasStackEntry *
|
static CoglRectangleMapStackEntry *
|
||||||
_cogl_atlas_stack_push (CoglAtlasStackEntry *stack,
|
_cogl_rectangle_map_stack_push (CoglRectangleMapStackEntry *stack,
|
||||||
CoglAtlasNode *node,
|
CoglRectangleMapNode *node,
|
||||||
gboolean next_index)
|
gboolean next_index)
|
||||||
{
|
{
|
||||||
CoglAtlasStackEntry *new_entry = g_slice_new (CoglAtlasStackEntry);
|
CoglRectangleMapStackEntry *new_entry =
|
||||||
|
g_slice_new (CoglRectangleMapStackEntry);
|
||||||
|
|
||||||
new_entry->node = node;
|
new_entry->node = node;
|
||||||
new_entry->next_index = next_index;
|
new_entry->next_index = next_index;
|
||||||
@ -155,18 +156,18 @@ _cogl_atlas_stack_push (CoglAtlasStackEntry *stack,
|
|||||||
return new_entry;
|
return new_entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CoglAtlasStackEntry *
|
static CoglRectangleMapStackEntry *
|
||||||
_cogl_atlas_stack_pop (CoglAtlasStackEntry *stack)
|
_cogl_rectangle_map_stack_pop (CoglRectangleMapStackEntry *stack)
|
||||||
{
|
{
|
||||||
CoglAtlasStackEntry *next = stack->next;
|
CoglRectangleMapStackEntry *next = stack->next;
|
||||||
|
|
||||||
g_slice_free (CoglAtlasStackEntry, stack);
|
g_slice_free (CoglRectangleMapStackEntry, stack);
|
||||||
|
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CoglAtlasNode *
|
static CoglRectangleMapNode *
|
||||||
_cogl_atlas_node_split_horizontally (CoglAtlasNode *node,
|
_cogl_rectangle_map_node_split_horizontally (CoglRectangleMapNode *node,
|
||||||
unsigned int left_width)
|
unsigned int left_width)
|
||||||
{
|
{
|
||||||
/* Splits the node horizontally (according to emacs' definition, not
|
/* Splits the node horizontally (according to emacs' definition, not
|
||||||
@ -175,13 +176,13 @@ _cogl_atlas_node_split_horizontally (CoglAtlasNode *node,
|
|||||||
will be returned. If the node is already just the right size it
|
will be returned. If the node is already just the right size it
|
||||||
won't do anything */
|
won't do anything */
|
||||||
|
|
||||||
CoglAtlasNode *left_node, *right_node;
|
CoglRectangleMapNode *left_node, *right_node;
|
||||||
|
|
||||||
if (node->rectangle.width == left_width)
|
if (node->rectangle.width == left_width)
|
||||||
return node;
|
return node;
|
||||||
|
|
||||||
left_node = _cogl_atlas_node_new ();
|
left_node = _cogl_rectangle_map_node_new ();
|
||||||
left_node->type = COGL_ATLAS_EMPTY_LEAF;
|
left_node->type = COGL_RECTANGLE_MAP_EMPTY_LEAF;
|
||||||
left_node->parent = node;
|
left_node->parent = node;
|
||||||
left_node->rectangle.x = node->rectangle.x;
|
left_node->rectangle.x = node->rectangle.x;
|
||||||
left_node->rectangle.y = node->rectangle.y;
|
left_node->rectangle.y = node->rectangle.y;
|
||||||
@ -189,8 +190,8 @@ _cogl_atlas_node_split_horizontally (CoglAtlasNode *node,
|
|||||||
left_node->rectangle.height = node->rectangle.height;
|
left_node->rectangle.height = node->rectangle.height;
|
||||||
node->d.branch.left = left_node;
|
node->d.branch.left = left_node;
|
||||||
|
|
||||||
right_node = _cogl_atlas_node_new ();
|
right_node = _cogl_rectangle_map_node_new ();
|
||||||
right_node->type = COGL_ATLAS_EMPTY_LEAF;
|
right_node->type = COGL_RECTANGLE_MAP_EMPTY_LEAF;
|
||||||
right_node->parent = node;
|
right_node->parent = node;
|
||||||
right_node->rectangle.x = node->rectangle.x + left_width;
|
right_node->rectangle.x = node->rectangle.x + left_width;
|
||||||
right_node->rectangle.y = node->rectangle.y;
|
right_node->rectangle.y = node->rectangle.y;
|
||||||
@ -198,13 +199,13 @@ _cogl_atlas_node_split_horizontally (CoglAtlasNode *node,
|
|||||||
right_node->rectangle.height = node->rectangle.height;
|
right_node->rectangle.height = node->rectangle.height;
|
||||||
node->d.branch.right = right_node;
|
node->d.branch.right = right_node;
|
||||||
|
|
||||||
node->type = COGL_ATLAS_BRANCH;
|
node->type = COGL_RECTANGLE_MAP_BRANCH;
|
||||||
|
|
||||||
return left_node;
|
return left_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CoglAtlasNode *
|
static CoglRectangleMapNode *
|
||||||
_cogl_atlas_node_split_vertically (CoglAtlasNode *node,
|
_cogl_rectangle_map_node_split_vertically (CoglRectangleMapNode *node,
|
||||||
unsigned int top_height)
|
unsigned int top_height)
|
||||||
{
|
{
|
||||||
/* Splits the node vertically (according to emacs' definition, not
|
/* Splits the node vertically (according to emacs' definition, not
|
||||||
@ -213,13 +214,13 @@ _cogl_atlas_node_split_vertically (CoglAtlasNode *node,
|
|||||||
will be returned. If the node is already just the right size it
|
will be returned. If the node is already just the right size it
|
||||||
won't do anything */
|
won't do anything */
|
||||||
|
|
||||||
CoglAtlasNode *top_node, *bottom_node;
|
CoglRectangleMapNode *top_node, *bottom_node;
|
||||||
|
|
||||||
if (node->rectangle.height == top_height)
|
if (node->rectangle.height == top_height)
|
||||||
return node;
|
return node;
|
||||||
|
|
||||||
top_node = _cogl_atlas_node_new ();
|
top_node = _cogl_rectangle_map_node_new ();
|
||||||
top_node->type = COGL_ATLAS_EMPTY_LEAF;
|
top_node->type = COGL_RECTANGLE_MAP_EMPTY_LEAF;
|
||||||
top_node->parent = node;
|
top_node->parent = node;
|
||||||
top_node->rectangle.x = node->rectangle.x;
|
top_node->rectangle.x = node->rectangle.x;
|
||||||
top_node->rectangle.y = node->rectangle.y;
|
top_node->rectangle.y = node->rectangle.y;
|
||||||
@ -227,8 +228,8 @@ _cogl_atlas_node_split_vertically (CoglAtlasNode *node,
|
|||||||
top_node->rectangle.height = top_height;
|
top_node->rectangle.height = top_height;
|
||||||
node->d.branch.left = top_node;
|
node->d.branch.left = top_node;
|
||||||
|
|
||||||
bottom_node = _cogl_atlas_node_new ();
|
bottom_node = _cogl_rectangle_map_node_new ();
|
||||||
bottom_node->type = COGL_ATLAS_EMPTY_LEAF;
|
bottom_node->type = COGL_RECTANGLE_MAP_EMPTY_LEAF;
|
||||||
bottom_node->parent = node;
|
bottom_node->parent = node;
|
||||||
bottom_node->rectangle.x = node->rectangle.x;
|
bottom_node->rectangle.x = node->rectangle.x;
|
||||||
bottom_node->rectangle.y = node->rectangle.y + top_height;
|
bottom_node->rectangle.y = node->rectangle.y + top_height;
|
||||||
@ -236,36 +237,36 @@ _cogl_atlas_node_split_vertically (CoglAtlasNode *node,
|
|||||||
bottom_node->rectangle.height = node->rectangle.height - top_height;
|
bottom_node->rectangle.height = node->rectangle.height - top_height;
|
||||||
node->d.branch.right = bottom_node;
|
node->d.branch.right = bottom_node;
|
||||||
|
|
||||||
node->type = COGL_ATLAS_BRANCH;
|
node->type = COGL_RECTANGLE_MAP_BRANCH;
|
||||||
|
|
||||||
return top_node;
|
return top_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
_cogl_atlas_add_rectangle (CoglAtlas *atlas,
|
_cogl_rectangle_map_add (CoglRectangleMap *map,
|
||||||
unsigned int width,
|
unsigned int width,
|
||||||
unsigned int height,
|
unsigned int height,
|
||||||
gpointer data,
|
void *data,
|
||||||
CoglAtlasRectangle *rectangle)
|
CoglRectangleMapEntry *rectangle)
|
||||||
{
|
{
|
||||||
/* Stack of nodes to search in */
|
/* Stack of nodes to search in */
|
||||||
CoglAtlasStackEntry *node_stack;
|
CoglRectangleMapStackEntry *node_stack;
|
||||||
CoglAtlasNode *found_node = NULL;
|
CoglRectangleMapNode *found_node = NULL;
|
||||||
|
|
||||||
/* Zero-sized rectangles break the algorithm for removing rectangles
|
/* Zero-sized rectangles break the algorithm for removing rectangles
|
||||||
so we'll disallow them */
|
so we'll disallow them */
|
||||||
g_return_val_if_fail (width > 0 && height > 0, FALSE);
|
g_return_val_if_fail (width > 0 && height > 0, FALSE);
|
||||||
|
|
||||||
/* Start with the root node */
|
/* Start with the root node */
|
||||||
node_stack = _cogl_atlas_stack_push (NULL, atlas->root, FALSE);
|
node_stack = _cogl_rectangle_map_stack_push (NULL, map->root, FALSE);
|
||||||
|
|
||||||
/* Depth-first search for an empty node that is big enough */
|
/* Depth-first search for an empty node that is big enough */
|
||||||
while (node_stack)
|
while (node_stack)
|
||||||
{
|
{
|
||||||
/* Pop an entry off the stack */
|
/* Pop an entry off the stack */
|
||||||
CoglAtlasNode *node = node_stack->node;
|
CoglRectangleMapNode *node = node_stack->node;
|
||||||
int next_index = node_stack->next_index;
|
int next_index = node_stack->next_index;
|
||||||
node_stack = _cogl_atlas_stack_pop (node_stack);
|
node_stack = _cogl_rectangle_map_stack_pop (node_stack);
|
||||||
|
|
||||||
/* Regardless of the type of the node, there's no point
|
/* Regardless of the type of the node, there's no point
|
||||||
descending any further if the new rectangle won't fit within
|
descending any further if the new rectangle won't fit within
|
||||||
@ -273,28 +274,31 @@ _cogl_atlas_add_rectangle (CoglAtlas *atlas,
|
|||||||
if (node->rectangle.width >= width &&
|
if (node->rectangle.width >= width &&
|
||||||
node->rectangle.height >= height)
|
node->rectangle.height >= height)
|
||||||
{
|
{
|
||||||
if (node->type == COGL_ATLAS_EMPTY_LEAF)
|
if (node->type == COGL_RECTANGLE_MAP_EMPTY_LEAF)
|
||||||
{
|
{
|
||||||
/* We've found a node we can use */
|
/* We've found a node we can use */
|
||||||
found_node = node;
|
found_node = node;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (node->type == COGL_ATLAS_BRANCH)
|
else if (node->type == COGL_RECTANGLE_MAP_BRANCH)
|
||||||
{
|
{
|
||||||
if (next_index)
|
if (next_index)
|
||||||
/* Try the right branch */
|
/* Try the right branch */
|
||||||
node_stack = _cogl_atlas_stack_push (node_stack,
|
node_stack =
|
||||||
|
_cogl_rectangle_map_stack_push (node_stack,
|
||||||
node->d.branch.right,
|
node->d.branch.right,
|
||||||
0);
|
0);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Make sure we remember to try the right branch once
|
/* Make sure we remember to try the right branch once
|
||||||
we've finished descending the left branch */
|
we've finished descending the left branch */
|
||||||
node_stack = _cogl_atlas_stack_push (node_stack,
|
node_stack =
|
||||||
|
_cogl_rectangle_map_stack_push (node_stack,
|
||||||
node,
|
node,
|
||||||
1);
|
1);
|
||||||
/* Try the left branch */
|
/* Try the left branch */
|
||||||
node_stack = _cogl_atlas_stack_push (node_stack,
|
node_stack =
|
||||||
|
_cogl_rectangle_map_stack_push (node_stack,
|
||||||
node->d.branch.left,
|
node->d.branch.left,
|
||||||
0);
|
0);
|
||||||
}
|
}
|
||||||
@ -304,7 +308,7 @@ _cogl_atlas_add_rectangle (CoglAtlas *atlas,
|
|||||||
|
|
||||||
/* Free the stack */
|
/* Free the stack */
|
||||||
while (node_stack)
|
while (node_stack)
|
||||||
node_stack = _cogl_atlas_stack_pop (node_stack);
|
node_stack = _cogl_rectangle_map_stack_pop (node_stack);
|
||||||
|
|
||||||
if (found_node)
|
if (found_node)
|
||||||
{
|
{
|
||||||
@ -313,29 +317,33 @@ _cogl_atlas_add_rectangle (CoglAtlas *atlas,
|
|||||||
if (found_node->rectangle.width - width >
|
if (found_node->rectangle.width - width >
|
||||||
found_node->rectangle.height - height)
|
found_node->rectangle.height - height)
|
||||||
{
|
{
|
||||||
found_node = _cogl_atlas_node_split_horizontally (found_node, width);
|
found_node =
|
||||||
found_node = _cogl_atlas_node_split_vertically (found_node, height);
|
_cogl_rectangle_map_node_split_horizontally (found_node, width);
|
||||||
|
found_node =
|
||||||
|
_cogl_rectangle_map_node_split_vertically (found_node, height);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
found_node = _cogl_atlas_node_split_vertically (found_node, height);
|
found_node =
|
||||||
found_node = _cogl_atlas_node_split_horizontally (found_node, width);
|
_cogl_rectangle_map_node_split_vertically (found_node, height);
|
||||||
|
found_node =
|
||||||
|
_cogl_rectangle_map_node_split_horizontally (found_node, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
found_node->type = COGL_ATLAS_FILLED_LEAF;
|
found_node->type = COGL_RECTANGLE_MAP_FILLED_LEAF;
|
||||||
found_node->d.data = data;
|
found_node->d.data = data;
|
||||||
if (rectangle)
|
if (rectangle)
|
||||||
*rectangle = found_node->rectangle;
|
*rectangle = found_node->rectangle;
|
||||||
|
|
||||||
/* Record how much empty space is remaining after this rectangle
|
/* Record how much empty space is remaining after this rectangle
|
||||||
is added */
|
is added */
|
||||||
g_assert (width * height <= atlas->space_remaining);
|
g_assert (width * height <= map->space_remaining);
|
||||||
atlas->space_remaining -= width * height;
|
map->space_remaining -= width * height;
|
||||||
atlas->n_rectangles++;
|
map->n_rectangles++;
|
||||||
|
|
||||||
#ifdef COGL_ENABLE_DEBUG
|
#ifdef COGL_ENABLE_DEBUG
|
||||||
if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DUMP_ATLAS_IMAGE))
|
if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DUMP_ATLAS_IMAGE))
|
||||||
_cogl_atlas_dump_image (atlas);
|
_cogl_rectangle_map_dump_image (map);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -345,15 +353,15 @@ _cogl_atlas_add_rectangle (CoglAtlas *atlas,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_atlas_remove_rectangle (CoglAtlas *atlas,
|
_cogl_rectangle_map_remove (CoglRectangleMap *map,
|
||||||
const CoglAtlasRectangle *rectangle)
|
const CoglRectangleMapEntry *rectangle)
|
||||||
{
|
{
|
||||||
CoglAtlasNode *node = atlas->root;
|
CoglRectangleMapNode *node = map->root;
|
||||||
|
|
||||||
/* We can do a binary-chop down the search tree to find the rectangle */
|
/* We can do a binary-chop down the search tree to find the rectangle */
|
||||||
while (node->type == COGL_ATLAS_BRANCH)
|
while (node->type == COGL_RECTANGLE_MAP_BRANCH)
|
||||||
{
|
{
|
||||||
CoglAtlasNode *left_node = node->d.branch.left;
|
CoglRectangleMapNode *left_node = node->d.branch.left;
|
||||||
|
|
||||||
/* If and only if the rectangle is in the left node then the x,y
|
/* If and only if the rectangle is in the left node then the x,y
|
||||||
position of the rectangle will be within the node's
|
position of the rectangle will be within the node's
|
||||||
@ -368,101 +376,101 @@ _cogl_atlas_remove_rectangle (CoglAtlas *atlas,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure we found the right node */
|
/* Make sure we found the right node */
|
||||||
if (node->type != COGL_ATLAS_FILLED_LEAF ||
|
if (node->type != COGL_RECTANGLE_MAP_FILLED_LEAF ||
|
||||||
node->rectangle.x != rectangle->x ||
|
node->rectangle.x != rectangle->x ||
|
||||||
node->rectangle.y != rectangle->y ||
|
node->rectangle.y != rectangle->y ||
|
||||||
node->rectangle.width != rectangle->width ||
|
node->rectangle.width != rectangle->width ||
|
||||||
node->rectangle.height != rectangle->height)
|
node->rectangle.height != rectangle->height)
|
||||||
/* This should only happen if someone tried to remove a rectangle
|
/* This should only happen if someone tried to remove a rectangle
|
||||||
that was not in the atlas so something has gone wrong */
|
that was not in the map so something has gone wrong */
|
||||||
g_return_if_reached ();
|
g_return_if_reached ();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Convert the node back to an empty node */
|
/* Convert the node back to an empty node */
|
||||||
if (atlas->value_destroy_func)
|
if (map->value_destroy_func)
|
||||||
atlas->value_destroy_func (node->d.data);
|
map->value_destroy_func (node->d.data);
|
||||||
node->type = COGL_ATLAS_EMPTY_LEAF;
|
node->type = COGL_RECTANGLE_MAP_EMPTY_LEAF;
|
||||||
|
|
||||||
/* Walk back up the tree combining branch nodes that have two
|
/* Walk back up the tree combining branch nodes that have two
|
||||||
empty leaves back into a single empty leaf */
|
empty leaves back into a single empty leaf */
|
||||||
for (node = node->parent; node; node = node->parent)
|
for (node = node->parent; node; node = node->parent)
|
||||||
{
|
{
|
||||||
/* This node is a parent so it should always be a branch */
|
/* This node is a parent so it should always be a branch */
|
||||||
g_assert (node->type == COGL_ATLAS_BRANCH);
|
g_assert (node->type == COGL_RECTANGLE_MAP_BRANCH);
|
||||||
|
|
||||||
if (node->d.branch.left->type == COGL_ATLAS_EMPTY_LEAF &&
|
if (node->d.branch.left->type == COGL_RECTANGLE_MAP_EMPTY_LEAF &&
|
||||||
node->d.branch.right->type == COGL_ATLAS_EMPTY_LEAF)
|
node->d.branch.right->type == COGL_RECTANGLE_MAP_EMPTY_LEAF)
|
||||||
{
|
{
|
||||||
_cogl_atlas_node_free (node->d.branch.left);
|
_cogl_rectangle_map_node_free (node->d.branch.left);
|
||||||
_cogl_atlas_node_free (node->d.branch.right);
|
_cogl_rectangle_map_node_free (node->d.branch.right);
|
||||||
node->type = COGL_ATLAS_EMPTY_LEAF;
|
node->type = COGL_RECTANGLE_MAP_EMPTY_LEAF;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* There is now more free space and one less rectangle */
|
/* There is now more free space and one less rectangle */
|
||||||
atlas->space_remaining += rectangle->width * rectangle->height;
|
map->space_remaining += rectangle->width * rectangle->height;
|
||||||
g_assert (atlas->n_rectangles > 0);
|
g_assert (map->n_rectangles > 0);
|
||||||
atlas->n_rectangles--;
|
map->n_rectangles--;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef COGL_ENABLE_DEBUG
|
#ifdef COGL_ENABLE_DEBUG
|
||||||
if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DUMP_ATLAS_IMAGE))
|
if (G_UNLIKELY (cogl_debug_flags & COGL_DEBUG_DUMP_ATLAS_IMAGE))
|
||||||
_cogl_atlas_dump_image (atlas);
|
_cogl_rectangle_map_dump_image (map);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
_cogl_atlas_get_width (CoglAtlas *atlas)
|
_cogl_rectangle_map_get_width (CoglRectangleMap *map)
|
||||||
{
|
{
|
||||||
return atlas->root->rectangle.width;
|
return map->root->rectangle.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
_cogl_atlas_get_height (CoglAtlas *atlas)
|
_cogl_rectangle_map_get_height (CoglRectangleMap *map)
|
||||||
{
|
{
|
||||||
return atlas->root->rectangle.height;
|
return map->root->rectangle.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
_cogl_atlas_get_remaining_space (CoglAtlas *atlas)
|
_cogl_rectangle_map_get_remaining_space (CoglRectangleMap *map)
|
||||||
{
|
{
|
||||||
return atlas->space_remaining;
|
return map->space_remaining;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
_cogl_atlas_get_n_rectangles (CoglAtlas *atlas)
|
_cogl_rectangle_map_get_n_rectangles (CoglRectangleMap *map)
|
||||||
{
|
{
|
||||||
return atlas->n_rectangles;
|
return map->n_rectangles;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cogl_atlas_internal_foreach (CoglAtlas *atlas,
|
_cogl_rectangle_map_internal_foreach (CoglRectangleMap *map,
|
||||||
CoglAtlasInternalForeachCb callback,
|
CoglRectangleMapInternalForeachCb func,
|
||||||
gpointer data)
|
void *data)
|
||||||
{
|
{
|
||||||
/* Stack of nodes to search in */
|
/* Stack of nodes to search in */
|
||||||
CoglAtlasStackEntry *node_stack;
|
CoglRectangleMapStackEntry *node_stack;
|
||||||
|
|
||||||
/* Start with the root node */
|
/* Start with the root node */
|
||||||
node_stack = _cogl_atlas_stack_push (NULL, atlas->root, 0);
|
node_stack = _cogl_rectangle_map_stack_push (NULL, map->root, 0);
|
||||||
|
|
||||||
/* Iterate all nodes depth-first */
|
/* Iterate all nodes depth-first */
|
||||||
while (node_stack)
|
while (node_stack)
|
||||||
{
|
{
|
||||||
CoglAtlasNode *node = node_stack->node;
|
CoglRectangleMapNode *node = node_stack->node;
|
||||||
|
|
||||||
switch (node->type)
|
switch (node->type)
|
||||||
{
|
{
|
||||||
case COGL_ATLAS_BRANCH:
|
case COGL_RECTANGLE_MAP_BRANCH:
|
||||||
if (node_stack->next_index == 0)
|
if (node_stack->next_index == 0)
|
||||||
{
|
{
|
||||||
/* Next time we come back to this node, go to the right */
|
/* Next time we come back to this node, go to the right */
|
||||||
node_stack->next_index = 1;
|
node_stack->next_index = 1;
|
||||||
|
|
||||||
/* Explore the left branch next */
|
/* Explore the left branch next */
|
||||||
node_stack = _cogl_atlas_stack_push (node_stack,
|
node_stack = _cogl_rectangle_map_stack_push (node_stack,
|
||||||
node->d.branch.left,
|
node->d.branch.left,
|
||||||
0);
|
0);
|
||||||
}
|
}
|
||||||
@ -472,22 +480,22 @@ _cogl_atlas_internal_foreach (CoglAtlas *atlas,
|
|||||||
node_stack->next_index = 2;
|
node_stack->next_index = 2;
|
||||||
|
|
||||||
/* Explore the right branch next */
|
/* Explore the right branch next */
|
||||||
node_stack = _cogl_atlas_stack_push (node_stack,
|
node_stack = _cogl_rectangle_map_stack_push (node_stack,
|
||||||
node->d.branch.right,
|
node->d.branch.right,
|
||||||
0);
|
0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* We're finished with this node so we can call the callback */
|
/* We're finished with this node so we can call the callback */
|
||||||
callback (node, data);
|
func (node, data);
|
||||||
node_stack = _cogl_atlas_stack_pop (node_stack);
|
node_stack = _cogl_rectangle_map_stack_pop (node_stack);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* Some sort of leaf node, just call the callback */
|
/* Some sort of leaf node, just call the callback */
|
||||||
callback (node, data);
|
func (node, data);
|
||||||
node_stack = _cogl_atlas_stack_pop (node_stack);
|
node_stack = _cogl_rectangle_map_stack_pop (node_stack);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -496,65 +504,69 @@ _cogl_atlas_internal_foreach (CoglAtlas *atlas,
|
|||||||
g_assert (node_stack == NULL);
|
g_assert (node_stack == NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct _CoglAtlasForeachClosure
|
typedef struct _CoglRectangleMapForeachClosure
|
||||||
{
|
{
|
||||||
CoglAtlasCallback callback;
|
CoglRectangleMapCallback callback;
|
||||||
gpointer data;
|
void *data;
|
||||||
} CoglAtlasForeachClosure;
|
} CoglRectangleMapForeachClosure;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cogl_atlas_foreach_cb (CoglAtlasNode *node, gpointer data)
|
_cogl_rectangle_map_foreach_cb (CoglRectangleMapNode *node, void *data)
|
||||||
{
|
{
|
||||||
CoglAtlasForeachClosure *closure = data;
|
CoglRectangleMapForeachClosure *closure = data;
|
||||||
|
|
||||||
if (node->type == COGL_ATLAS_FILLED_LEAF)
|
if (node->type == COGL_RECTANGLE_MAP_FILLED_LEAF)
|
||||||
closure->callback (&node->rectangle, node->d.data, closure->data);
|
closure->callback (&node->rectangle, node->d.data, closure->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_atlas_foreach (CoglAtlas *atlas,
|
_cogl_rectangle_map_foreach (CoglRectangleMap *map,
|
||||||
CoglAtlasCallback callback,
|
CoglRectangleMapCallback callback,
|
||||||
gpointer data)
|
void *data)
|
||||||
{
|
{
|
||||||
CoglAtlasForeachClosure closure;
|
CoglRectangleMapForeachClosure closure;
|
||||||
|
|
||||||
closure.callback = callback;
|
closure.callback = callback;
|
||||||
closure.data = data;
|
closure.data = data;
|
||||||
|
|
||||||
_cogl_atlas_internal_foreach (atlas, _cogl_atlas_foreach_cb, &closure);
|
_cogl_rectangle_map_internal_foreach (map,
|
||||||
|
_cogl_rectangle_map_foreach_cb,
|
||||||
|
&closure);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cogl_atlas_free_cb (CoglAtlasNode *node, gpointer data)
|
_cogl_rectangle_map_free_cb (CoglRectangleMapNode *node, void *data)
|
||||||
{
|
{
|
||||||
CoglAtlas *atlas = data;
|
CoglRectangleMap *map = data;
|
||||||
|
|
||||||
if (node->type == COGL_ATLAS_FILLED_LEAF && atlas->value_destroy_func)
|
if (node->type == COGL_RECTANGLE_MAP_FILLED_LEAF && map->value_destroy_func)
|
||||||
atlas->value_destroy_func (node->d.data);
|
map->value_destroy_func (node->d.data);
|
||||||
|
|
||||||
_cogl_atlas_node_free (node);
|
_cogl_rectangle_map_node_free (node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_cogl_atlas_free (CoglAtlas *atlas)
|
_cogl_rectangle_map_free (CoglRectangleMap *map)
|
||||||
{
|
{
|
||||||
_cogl_atlas_internal_foreach (atlas, _cogl_atlas_free_cb, atlas);
|
_cogl_rectangle_map_internal_foreach (map,
|
||||||
g_free (atlas);
|
_cogl_rectangle_map_free_cb,
|
||||||
|
map);
|
||||||
|
g_free (map);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef COGL_ENABLE_DEBUG
|
#ifdef COGL_ENABLE_DEBUG
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cogl_atlas_dump_image_cb (CoglAtlasNode *node, gpointer data)
|
_cogl_rectangle_map_dump_image_cb (CoglRectangleMapNode *node, void *data)
|
||||||
{
|
{
|
||||||
cairo_t *cr = data;
|
cairo_t *cr = data;
|
||||||
|
|
||||||
if (node->type == COGL_ATLAS_FILLED_LEAF ||
|
if (node->type == COGL_RECTANGLE_MAP_FILLED_LEAF ||
|
||||||
node->type == COGL_ATLAS_EMPTY_LEAF)
|
node->type == COGL_RECTANGLE_MAP_EMPTY_LEAF)
|
||||||
{
|
{
|
||||||
/* Fill the rectangle using a different colour depending on
|
/* Fill the rectangle using a different colour depending on
|
||||||
whether the rectangle is used */
|
whether the rectangle is used */
|
||||||
if (node->type == COGL_ATLAS_FILLED_LEAF)
|
if (node->type == COGL_RECTANGLE_MAP_FILLED_LEAF)
|
||||||
cairo_set_source_rgb (cr, 0.0, 0.0, 1.0);
|
cairo_set_source_rgb (cr, 0.0, 0.0, 1.0);
|
||||||
else
|
else
|
||||||
cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
|
cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
|
||||||
@ -574,23 +586,25 @@ _cogl_atlas_dump_image_cb (CoglAtlasNode *node, gpointer data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cogl_atlas_dump_image (CoglAtlas *atlas)
|
_cogl_rectangle_map_dump_image (CoglRectangleMap *map)
|
||||||
{
|
{
|
||||||
/* This dumps a png to help visualize the atlas. Each leaf rectangle
|
/* This dumps a png to help visualize the map. Each leaf rectangle
|
||||||
is drawn with a white outline. Unused leaves are filled in black
|
is drawn with a white outline. Unused leaves are filled in black
|
||||||
and used leaves are blue */
|
and used leaves are blue */
|
||||||
|
|
||||||
cairo_surface_t *surface =
|
cairo_surface_t *surface =
|
||||||
cairo_image_surface_create (CAIRO_FORMAT_RGB24,
|
cairo_image_surface_create (CAIRO_FORMAT_RGB24,
|
||||||
_cogl_atlas_get_width (atlas),
|
_cogl_rectangle_map_get_width (map),
|
||||||
_cogl_atlas_get_height (atlas));
|
_cogl_rectangle_map_get_height (map));
|
||||||
cairo_t *cr = cairo_create (surface);
|
cairo_t *cr = cairo_create (surface);
|
||||||
|
|
||||||
_cogl_atlas_internal_foreach (atlas, _cogl_atlas_dump_image_cb, cr);
|
_cogl_rectangle_map_internal_foreach (map,
|
||||||
|
_cogl_rectangle_map_dump_image_cb,
|
||||||
|
cr);
|
||||||
|
|
||||||
cairo_destroy (cr);
|
cairo_destroy (cr);
|
||||||
|
|
||||||
cairo_surface_write_to_png (surface, "cogl-atlas-dump.png");
|
cairo_surface_write_to_png (surface, "cogl-rectangle-map-dump.png");
|
||||||
|
|
||||||
cairo_surface_destroy (surface);
|
cairo_surface_destroy (surface);
|
||||||
}
|
}
|
78
clutter/cogl/cogl/cogl-rectangle-map.h
Normal file
78
clutter/cogl/cogl/cogl-rectangle-map.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Cogl
|
||||||
|
*
|
||||||
|
* An object oriented GL/GLES Abstraction/Utility Layer
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Intel Corporation.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __COGL_RECTANGLE_MAP_H
|
||||||
|
#define __COGL_RECTANGLE_MAP_H
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
typedef struct _CoglRectangleMap CoglRectangleMap;
|
||||||
|
typedef struct _CoglRectangleMapEntry CoglRectangleMapEntry;
|
||||||
|
|
||||||
|
typedef void (* CoglRectangleMapCallback) (const CoglRectangleMapEntry *entry,
|
||||||
|
void *rectangle_data,
|
||||||
|
void *user_data);
|
||||||
|
|
||||||
|
struct _CoglRectangleMapEntry
|
||||||
|
{
|
||||||
|
unsigned int x, y;
|
||||||
|
unsigned int width, height;
|
||||||
|
};
|
||||||
|
|
||||||
|
CoglRectangleMap *
|
||||||
|
_cogl_rectangle_map_new (unsigned int width,
|
||||||
|
unsigned int height,
|
||||||
|
GDestroyNotify value_destroy_func);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
_cogl_rectangle_map_add (CoglRectangleMap *map,
|
||||||
|
unsigned int width,
|
||||||
|
unsigned int height,
|
||||||
|
void *data,
|
||||||
|
CoglRectangleMapEntry *rectangle);
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_rectangle_map_remove (CoglRectangleMap *map,
|
||||||
|
const CoglRectangleMapEntry *rectangle);
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
_cogl_rectangle_map_get_width (CoglRectangleMap *map);
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
_cogl_rectangle_map_get_height (CoglRectangleMap *map);
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
_cogl_rectangle_map_get_remaining_space (CoglRectangleMap *map);
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
_cogl_rectangle_map_get_n_rectangles (CoglRectangleMap *map);
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_rectangle_map_foreach (CoglRectangleMap *map,
|
||||||
|
CoglRectangleMapCallback callback,
|
||||||
|
void *data);
|
||||||
|
|
||||||
|
void
|
||||||
|
_cogl_rectangle_map_free (CoglRectangleMap *map);
|
||||||
|
|
||||||
|
#endif /* __COGL_RECTANGLE_MAP_H */
|
Loading…
Reference in New Issue
Block a user