From 6ec0202fba35eb878af793ed6086ff928f13ce5b Mon Sep 17 00:00:00 2001 From: Andy Spencer Date: Mon, 13 Feb 2012 23:12:20 +0000 Subject: [PATCH] Fix memory leaks in tile loading - Splitting a tile could accidentally overwrite a already split tile if one (but not all) of the children were garbage collected. - Garbage collection never actually happened.. because tile always had empty children. To fix this a `load' flag was added so that the children could be garbage collected as well without having to check the data flag which may always be null. tile->load: set when texture loading has started tile->data: set when texture loading has finished --- src/objects/grits-tile.c | 66 +++++++++++++++++++++++++--------------- src/objects/grits-tile.h | 1 + 2 files changed, 42 insertions(+), 25 deletions(-) diff --git a/src/objects/grits-tile.c b/src/objects/grits-tile.c index f536c96..f269e5e 100644 --- a/src/objects/grits-tile.c +++ b/src/objects/grits-tile.c @@ -64,8 +64,10 @@ GritsTile *grits_tile_new(GritsTile *parent, tile->atime = time(NULL); grits_bounds_set_bounds(&tile->coords, 0, 1, 1, 0); grits_bounds_set_bounds(&tile->edge, n, s, e, w); - if (parent) - tile->proj = parent->proj; + if (parent) { + tile->proj = parent->proj; + tile->zindex = parent->zindex+1; + } return tile; } @@ -149,12 +151,18 @@ static void _grits_tile_split_latlon(GritsTile *tile) const gdouble lon_step = lon_dist / cols; int row, col; - grits_tile_foreach_index(tile, row, col) - tile->children[row][col] = grits_tile_new(tile, - tile->edge.n - lat_step*(row+0), // north - tile->edge.n - lat_step*(row+1), // south - tile->edge.w + lon_step*(col+1), // east - tile->edge.w + lon_step*(col+0)); // west + grits_tile_foreach_index(tile, row, col) { + if (!tile->children[row][col]) + tile->children[row][col] = + grits_tile_new(tile, 0, 0, 0, 0); + /* Set edges aferwards so that north and south + * get reset for mercator projections */ + GritsTile *child = tile->children[row][col]; + child->edge.n = tile->edge.n - lat_step*(row+0); + child->edge.s = tile->edge.n - lat_step*(row+1); + child->edge.e = tile->edge.w + lon_step*(col+1); + child->edge.w = tile->edge.w + lon_step*(col+0); + } } static void _grits_tile_split_mercator(GritsTile *tile) @@ -196,26 +204,30 @@ void grits_tile_update(GritsTile *tile, GritsPoint *eye, gdouble res, gint width, gint height, GritsTileLoadFunc load_func, gpointer user_data) { - //g_debug("GritsTile: update - %p->atime = %u", - // tile, (guint)tile->atime); GritsTile *child; if (tile == NULL) return; - if (!tile->data) - load_func(tile, user_data); - - tile->atime = time(NULL); + //g_debug("GritsTile: update - %p->atime = %u", + // tile, (guint)tile->atime); - /* Is this tile high enough resolution? */ - if (_grits_tile_precise(eye, &tile->edge, res, width, height)) { - grits_tile_foreach(tile, child) - if (child) - GRITS_OBJECT(child)->hidden = TRUE; + /* Is the parent tile's texture high enough + * resolution for this part? */ + gint xs = G_N_ELEMENTS(tile->children); + gint ys = G_N_ELEMENTS(tile->children[0]); + if (_grits_tile_precise(eye, &tile->edge, res, width/xs, height/ys)) { + GRITS_OBJECT(tile)->hidden = TRUE; return; } + /* Load the tile */ + if (!tile->load && !tile->data) + load_func(tile, user_data); + tile->atime = time(NULL); + tile->load = TRUE; + GRITS_OBJECT(tile)->hidden = FALSE; + /* Split tile if needed */ grits_tile_foreach(tile, child) { if (child == NULL) { @@ -227,12 +239,9 @@ void grits_tile_update(GritsTile *tile, GritsPoint *eye, } /* Update recursively */ - grits_tile_foreach(tile, child) { - GRITS_OBJECT(child)->hidden = FALSE; + grits_tile_foreach(tile, child) grits_tile_update(child, eye, res, width, height, load_func, user_data); - } - } /** @@ -303,8 +312,10 @@ GritsTile *grits_tile_gc(GritsTile *root, time_t atime, } //g_debug("GritsTile: gc - %p->atime=%u < atime=%u", // root, (guint)root->atime, (guint)atime); - if (!has_children && root->atime < atime && root->data) { - free_func(root, user_data); + if (!has_children && root->atime < atime && + (root->data || !root->load)) { + if (root->data) + free_func(root, user_data); g_object_unref(root); return NULL; } @@ -459,6 +470,11 @@ static void grits_tile_draw_one(GritsTile *tile, GritsOpenGL *opengl, GList *tri /* Draw the tile */ static gboolean grits_tile_draw_rec(GritsTile *tile, GritsOpenGL *opengl) { + //g_debug("GritsTile: draw_rec - tile=%p, data=%d, load=%d, hide=%d", tile, + // tile ? !!tile->data : 0, + // tile ? !!tile->load : 0, + // tile ? !!GRITS_OBJECT(tile)->hidden : 0); + if (!tile || !tile->data || GRITS_OBJECT(tile)->hidden) return FALSE; diff --git a/src/objects/grits-tile.h b/src/objects/grits-tile.h index f2b706f..b13e1c3 100644 --- a/src/objects/grits-tile.h +++ b/src/objects/grits-tile.h @@ -37,6 +37,7 @@ struct _GritsTile { /* Pointer to the tile data */ gpointer data; + gboolean load; /* Drawing order */ gint zindex; -- 2.43.2