[grits] Fix memory leaks in tile loading



commit 6ec0202fba35eb878af793ed6086ff928f13ce5b
Author: Andy Spencer <andy753421 gmail com>
Date:   Mon Feb 13 23:12:20 2012 +0000

    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;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]