[grits] Move low level tile loading to GritsTile



commit 2f0edbabb90eb0c421419433e8893521257bc614
Author: Andy Spencer <andy753421 gmail com>
Date:   Thu Dec 27 03:23:01 2012 +0000

    Move low level tile loading to GritsTile
    
    Move all the OpenGL stuff out of the plugins and into GritsTile, this
    prevents needing to explicit idle callbacks in plugins, which is
    extremely unstable when unloading a plugin.
    
    Note: The tile code is _not_ thread safe and will be reworked in
    subsequent changes. The plan is to use some sort of priority queue and
    do all the updating and garbage collecting from the main thread directly
    from the location-changed callback. The plugins can still use thread
    pools for the actual downloading and loading.

 src/objects/grits-tile.c |  161 ++++++++++++++++++++++++++++++++++++++++++++--
 src/objects/grits-tile.h |   18 +++++
 src/plugins/elev.c       |  123 +++++++----------------------------
 src/plugins/map.c        |  106 ++++++------------------------
 src/plugins/sat.c        |   98 ++++++----------------------
 5 files changed, 236 insertions(+), 270 deletions(-)
---
diff --git a/src/objects/grits-tile.c b/src/objects/grits-tile.c
index 6ea70f8..b903492 100644
--- a/src/objects/grits-tile.c
+++ b/src/objects/grits-tile.c
@@ -224,7 +224,7 @@ void grits_tile_update(GritsTile *tile, GritsPoint *eye,
 	}
 
 	/* Load the tile */
-	if (!tile->load && !tile->data)
+	if (!tile->load && !tile->pixels && !tile->tex)
 		load_func(tile, user_data);
 	tile->atime = time(NULL);
 	tile->load  = TRUE;
@@ -247,6 +247,99 @@ void grits_tile_update(GritsTile *tile, GritsPoint *eye,
 }
 
 /**
+ * grits_tile_load_pixels:
+ * @tile:   the tile to load data into
+ * @pixels: buffered pixel data
+ * @width:  width of the pixel buffer (in pixels)
+ * @height: height of the pixel buffer (in pixels)
+ * @alpha:  TRUE if the pixel data contains an alpha channel
+ *
+ * Load tile data from an in memory pixel buffer.
+ *
+ * This function is thread safe and my be called from outside the main thread.
+ *
+ * Ownership of the pixel buffer is passed to the tile, it should not be freed
+ * or modified after calling this function.
+ *
+ * Returns: TRUE if the image was loaded successfully
+ */
+gboolean grits_tile_load_pixels(GritsTile *tile, guchar *pixels,
+		gint width, gint height, gint alpha)
+{
+	g_debug("GritsTile: load_pixels - %p -> %p (%dx%d:%d)",
+			tile, pixels, width, height, alpha);
+
+	/* Copy pixbuf data for callback */
+	tile->width  = width;
+	tile->height = height;
+	tile->alpha  = alpha;
+	tile->pixels = pixels;
+
+	/* Queue OpenGL texture load/draw */
+	grits_object_queue_draw(GRITS_OBJECT(tile));
+	return TRUE;
+}
+
+/**
+ * grits_tile_load_file:
+ * @tile: the tile to load data into
+ * @file: path to an image file to load
+ *
+ * Load tile data from a GdkPixbuf
+ * This function is thread safe and my be called from outside the main thread.
+ *
+ * Returns: TRUE if the image was loaded successfully
+ */
+gboolean grits_tile_load_pixbuf(GritsTile *tile, GdkPixbuf *pixbuf)
+{
+	g_debug("GritsTile: load_pixbuf %p -> %p", tile, pixbuf);
+
+	/* Copy pixbuf data for callback */
+	tile->pixbuf = g_object_ref(pixbuf);
+	tile->width  = gdk_pixbuf_get_width(pixbuf);
+	tile->height = gdk_pixbuf_get_height(pixbuf);
+	tile->alpha  = gdk_pixbuf_get_has_alpha(pixbuf);
+	tile->pixels = gdk_pixbuf_get_pixels(pixbuf);
+
+	/* Queue OpenGL texture load/draw */
+	grits_object_queue_draw(GRITS_OBJECT(tile));
+
+	return TRUE;
+}
+
+/**
+ * grits_tile_load_file:
+ * @tile: the tile to load data into
+ * @file: path to an image file to load
+ *
+ * Load tile data from an image file
+ * This function is thread safe and my be called from outside the main thread.
+ *
+ * Returns: TRUE if the image was loaded successfully
+ */
+gboolean grits_tile_load_file(GritsTile *tile, const gchar *file)
+{
+	g_debug("GritsTile: load_file %p -> %s", tile, file);
+
+	/* Load pixbuf */
+	GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(file, NULL);
+	if (!pixbuf)
+		return FALSE;
+
+	/* Copy pixbuf data for callback */
+	tile->pixbuf = pixbuf;
+	tile->width  = gdk_pixbuf_get_width(pixbuf);
+	tile->height = gdk_pixbuf_get_height(pixbuf);
+	tile->alpha  = gdk_pixbuf_get_has_alpha(pixbuf);
+	tile->pixels = gdk_pixbuf_get_pixels(pixbuf);
+
+	/* Queue OpenGL texture load/draw */
+	grits_object_queue_draw(GRITS_OBJECT(tile));
+
+	return TRUE;
+}
+
+/**
  * grits_tile_find:
  * @root: the root tile to search from
  * @lat:  target latitude
@@ -254,7 +347,7 @@ void grits_tile_update(GritsTile *tile, GritsPoint *eye,
  *
  * Locate the subtile with the highest resolution which contains the given
  * lat/lon point.
- * 
+ *
  * Returns: the child tile
  */
 GritsTile *grits_tile_find(GritsTile *root, gdouble lat, gdouble lon)
@@ -317,8 +410,17 @@ GritsTile *grits_tile_gc(GritsTile *root, time_t atime,
 	if (root->parent && !has_children && root->atime < atime &&
 			(root->data || !root->load)) {
 		//g_debug("GritsTile: gc/free - %p", root);
-		if (root->data)
-			free_func(root, user_data);
+		if (root->tex) {
+			glDeleteTextures(1, &root->tex);
+			root->tex = 0;
+		}
+		if (root->data) {
+			if (free_func)
+				free_func(root, user_data);
+			else
+				g_free(root->data);
+			root->data = NULL;
+		}
 		g_object_unref(root);
 		return NULL;
 	}
@@ -368,10 +470,55 @@ static guint _grits_tile_load_mask(void)
 	return tex;
 }
 
+/* Load the texture from saved pixel data */
+static gboolean _grits_tile_load_tex(GritsTile *tile)
+{
+	/* Abort for null tiles */
+	if (!tile)
+		return FALSE;
+
+	/* Defer loading of hidden tiles */
+	if (GRITS_OBJECT(tile)->hidden)
+		return FALSE;
+
+	/* If we're already done loading the text stop */
+	if (tile->tex)
+		return TRUE;
+
+	/* Check if the tile has data yet */
+	if (!tile->pixels)
+		return FALSE;
+
+	/* Create texture */
+	g_debug("GritsTile: load_tex");
+	glGenTextures(1, &tile->tex);
+	glBindTexture(GL_TEXTURE_2D, tile->tex);
+
+	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+	glPixelStorei(GL_PACK_ALIGNMENT, 1);
+	glTexImage2D(GL_TEXTURE_2D, 0, 4, tile->width, tile->height, 0,
+			(tile->alpha ? GL_RGBA : GL_RGB), GL_UNSIGNED_BYTE, tile->pixels);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+	/* Free data */
+	if (tile->pixbuf)
+		g_object_unref(tile->pixbuf);
+	else
+		g_free(tile->pixels);
+	tile->pixbuf = NULL;
+	tile->pixels = NULL;
+
+	return TRUE;
+
+}
+
 /* Draw a single tile */
 static void grits_tile_draw_one(GritsTile *tile, GritsOpenGL *opengl, GList *triangles)
 {
-	if (!tile || !tile->data)
+	if (!tile || !tile->tex)
 		return;
 	if (!triangles)
 		g_warning("GritsOpenGL: _draw_tiles - No triangles to draw: edges=%f,%f,%f,%f",
@@ -437,7 +584,7 @@ static void grits_tile_draw_one(GritsTile *tile, GritsOpenGL *opengl, GList *tri
 		}
 
 		/* Draw triangle */
-		glBindTexture(GL_TEXTURE_2D, *(guint*)tile->data);
+		glBindTexture(GL_TEXTURE_2D, tile->tex);
 		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 		glBegin(GL_TRIANGLES);
 		glNormal3dv(tri->p.r->norm); glMultiTexCoord2dv(GL_TEXTURE0, xy[0]); glMultiTexCoord2dv(GL_TEXTURE1, xy[0]); glVertex3dv((double*)tri->p.r);
@@ -455,7 +602,7 @@ static gboolean grits_tile_draw_rec(GritsTile *tile, GritsOpenGL *opengl)
 	//		tile ? !!tile->load : 0,
 	//		tile ? !!GRITS_OBJECT(tile)->hidden : 0);
 
-	if (!tile || !tile->data || GRITS_OBJECT(tile)->hidden)
+	if (!_grits_tile_load_tex(tile))
 		return FALSE;
 
 	GritsTile *child = NULL;
diff --git a/src/objects/grits-tile.h b/src/objects/grits-tile.h
index b13e1c3..fc87695 100644
--- a/src/objects/grits-tile.h
+++ b/src/objects/grits-tile.h
@@ -57,6 +57,14 @@ struct _GritsTile {
 
 	/* Projection used by tile data */
 	GritsProj proj;
+
+	/* Internal data to the tile */
+	guint      tex;
+	GdkPixbuf *pixbuf;
+	guchar    *pixels;
+	gint       width;
+	gint       height;
+	gint       alpha;
 };
 
 struct _GritsTileClass {
@@ -125,6 +133,16 @@ void grits_tile_update(GritsTile *root, GritsPoint *eye,
 		gdouble res, gint width, gint height,
 		GritsTileLoadFunc load_func, gpointer user_data);
 
+/* Load tile data from pixel buffer */
+gboolean grits_tile_load_pixels(GritsTile *tile, guchar *pixels,
+		gint width, gint height, gint channels);
+
+/* Load tile data from a GdkPixbuf */
+gboolean grits_tile_load_pixbuf(GritsTile *tile, GdkPixbuf *pixbuf);
+
+/* Load tile data from an image file */
+gboolean grits_tile_load_file(GritsTile *tile, const gchar *file);
+
 /* Find the leaf tile containing lat-lon */
 GritsTile *grits_tile_find(GritsTile *root, gdouble lat, gdouble lon);
 
diff --git a/src/plugins/elev.c b/src/plugins/elev.c
index db7b977..3f7b2a1 100644
--- a/src/plugins/elev.c
+++ b/src/plugins/elev.c
@@ -43,12 +43,6 @@
 #define TILE_CHANNELS  4
 #define TILE_SIZE      (TILE_WIDTH*TILE_HEIGHT*sizeof(guint16))
 
-struct _TileData {
-	/* OpenGL has to be first to make grits_tile_draw happy */
-	guint    tex;
-	guint16 *bil;
-};
-
 static gdouble _height_func(gdouble lat, gdouble lon, gpointer _elev)
 {
 	GritsPluginElev *elev = _elev;
@@ -57,10 +51,7 @@ static gdouble _height_func(gdouble lat, gdouble lon, gpointer _elev)
 	GritsTile *tile = grits_tile_find(elev->tiles, lat, lon);
 	if (!tile) return 0;
 
-	struct _TileData *data = tile->data;
-	if (!data) return 0;
-
-	guint16 *bil  = data->bil;
+	guint16 *bil = tile->data;
 	if (!bil)  return 0;
 
 	gint w = TILE_WIDTH;
@@ -104,13 +95,6 @@ static gdouble _height_func(gdouble lat, gdouble lon, gpointer _elev)
  * Loader and Freeers *
  **********************/
 
-struct _LoadTileData {
-	GritsPluginElev  *elev;
-	GritsTile        *tile;
-	guint8           *pixels;
-	struct _TileData *tdata;
-};
-
 static guint16 *_load_bil(gchar *path)
 {
 	gsize len;
@@ -149,53 +133,9 @@ static guchar *_load_pixels(guint16 *bil)
 	return (guchar*)pixels;
 }
 
-static gboolean _load_tile_cb(gpointer _data)
-{
-	struct _LoadTileData *data  = _data;
-	struct _TileData     *tdata = data->tdata;
-	g_debug("GritsPluginElev: _load_tile_cb start");
-	if (data->elev->aborted) {
-		g_debug("GritsPluginElev: _load_tile - aborted");
-		return FALSE;
-	}
-
-	/* Load OpenGL texture (from main thread) */
-	if (data->pixels) {
-		glGenTextures(1, &tdata->tex);
-		glBindTexture(GL_TEXTURE_2D, tdata->tex);
-
-		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-		glPixelStorei(GL_PACK_ALIGNMENT, 1);
-		glTexImage2D(GL_TEXTURE_2D, 0, TILE_CHANNELS, TILE_WIDTH, TILE_HEIGHT, 0,
-				GL_RGBA, GL_UNSIGNED_BYTE, data->pixels);
-		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-		glFlush();
-	}
-
-	/* Set hight function (from main thread) */
-	if (tdata->bil) {
-		grits_viewer_set_height_func(data->elev->viewer, &data->tile->edge,
-				_height_func, data->elev, TRUE);
-	}
-
-	/* Queue tiles for drawing */
-	data->tile->data = tdata;
-	gtk_widget_queue_draw(GTK_WIDGET(data->elev->viewer));
-
-	/* Cleanup */
-	g_free(data->pixels);
-	g_free(data);
-	return FALSE;
-}
-
 static void _load_tile(GritsTile *tile, gpointer _elev)
 {
 	GritsPluginElev *elev = _elev;
-	guint16 *bil    = NULL;
-	guchar  *pixels = NULL;
 
 	g_debug("GritsPluginElev: _load_tile start %p", g_thread_self());
 	if (elev->aborted) {
@@ -205,51 +145,37 @@ static void _load_tile(GritsTile *tile, gpointer _elev)
 
 	/* Download tile */
 	gchar *path = grits_wms_fetch(elev->wms, tile, GRITS_ONCE, NULL, NULL);
-	if (!path) return;
+	if (!path)
+		return;
 
 	/* Load bil */
-	bil = _load_bil(path);
+	guint16 *bil = _load_bil(path);
 	g_free(path);
-	if (!bil) return;
+	if (!bil)
+		return;
 
-	/* Load pixels */
-	if (LOAD_TEX)
-		pixels = _load_pixels(bil);
+	/* Set hight function (TODO: from main thread?) */
+	if (LOAD_BIL) {
+		tile->data = bil;
+		grits_viewer_set_height_func(elev->viewer, &tile->edge,
+				_height_func, elev, TRUE);
+	}
+
+	/* Load pixels for grayscale height textures */
+	if (LOAD_TEX) {
+		guchar *pixels = _load_pixels(bil);
+		grits_tile_load_pixels(tile, pixels,
+			TILE_WIDTH, TILE_HEIGHT, TILE_CHANNELS==4);
+	}
+
+	/* Free bill if we're not interested in a hight function */
 	if (!LOAD_BIL)
 		g_free(bil);
 
-	/* Copy pixbuf data for callback */
-	struct _LoadTileData *data  = g_new0(struct _LoadTileData, 1);
-	struct _TileData     *tdata = g_new0(struct _TileData,     1);
-	data->elev   = elev;
-	data->tile   = tile;
-	data->pixels = pixels;
-	data->tdata  = tdata;
-	tdata->tex   = 0;
-	tdata->bil   = bil;
-
 	/* Load the GL texture from the main thread */
-	g_idle_add_full(G_PRIORITY_LOW, _load_tile_cb, data, NULL);
 	g_debug("GritsPluginElev: _load_tile end %p", g_thread_self());
 }
 
-static gboolean _free_tile_cb(gpointer _data)
-{
-	struct _TileData *data = _data;
-	if (LOAD_BIL)
-		g_free(data->bil);
-	if (LOAD_TEX)
-		glDeleteTextures(1, &data->tex);
-	g_free(data);
-	return FALSE;
-}
-static void _free_tile(GritsTile *tile, gpointer _elev)
-{
-	g_debug("GritsPluginElev: _free_tile: %p", tile->data);
-	if (tile->data)
-		g_idle_add_full(G_PRIORITY_LOW, _free_tile_cb, tile->data, NULL);
-}
-
 static void _update_tiles(gpointer _, gpointer _elev)
 {
 	g_debug("GritsPluginElev: _update_tiles");
@@ -259,8 +185,7 @@ static void _update_tiles(gpointer _, gpointer _elev)
 	grits_tile_update(elev->tiles, &eye,
 			MAX_RESOLUTION, TILE_WIDTH, TILE_WIDTH,
 			_load_tile, elev);
-	grits_tile_gc(elev->tiles, time(NULL)-10,
-			_free_tile, elev);
+	grits_tile_gc(elev->tiles, time(NULL)-10, NULL, elev);
 }
 
 /*************
@@ -346,8 +271,6 @@ static void grits_plugin_elev_dispose(GObject *gobject)
 		g_object_unref(elev->tiles);
 		soup_session_abort(elev->wms->http->soup);
 		g_thread_pool_free(elev->threads, TRUE, TRUE);
-		while (gtk_events_pending())
-			gtk_main_iteration();
 		g_object_unref(viewer);
 	}
 	G_OBJECT_CLASS(grits_plugin_elev_parent_class)->dispose(gobject);
@@ -358,7 +281,7 @@ static void grits_plugin_elev_finalize(GObject *gobject)
 	GritsPluginElev *elev = GRITS_PLUGIN_ELEV(gobject);
 	/* Free data */
 	grits_wms_free(elev->wms);
-	grits_tile_free(elev->tiles, _free_tile, elev);
+	grits_tile_free(elev->tiles, NULL, elev);
 	G_OBJECT_CLASS(grits_plugin_elev_parent_class)->finalize(gobject);
 
 }
diff --git a/src/plugins/map.c b/src/plugins/map.c
index 13f986c..a573dcb 100644
--- a/src/plugins/map.c
+++ b/src/plugins/map.c
@@ -33,57 +33,19 @@
 #define MAX_RESOLUTION 1
 #define TILE_WIDTH     256
 #define TILE_HEIGHT    256
+
 //#define MAX_RESOLUTION 100
 //#define TILE_WIDTH     1024
 //#define TILE_HEIGHT    512
 
 static const guchar colormap[][2][4] = {
-	//{{0x73, 0x91, 0xad}, {0x73, 0x91, 0xad, 0x00}}, // Oceans
-	//{{0xf6, 0xee, 0xee}, {0xf6, 0xee, 0xee, 0x00}}, // Ground
-	//{{0xff, 0xff, 0xff}, {0xff, 0xff, 0xff, 0xff}}, // Borders
-	//{{0x73, 0x93, 0xad}, {0x73, 0x93, 0xad, 0x40}}, // Lakes
-	//{{0xff, 0xe1, 0x80}, {0xff, 0xe1, 0x80, 0x60}}, // Cities
+	{{0x73, 0x91, 0xad}, {0x73, 0x91, 0xad, 0x00}}, // Oceans
+	{{0xf6, 0xee, 0xee}, {0xf6, 0xee, 0xee, 0x00}}, // Ground
+	{{0xff, 0xff, 0xff}, {0xff, 0xff, 0xff, 0xff}}, // Borders
+	{{0x73, 0x93, 0xad}, {0x73, 0x93, 0xad, 0x40}}, // Lakes
+	{{0xff, 0xe1, 0x80}, {0xff, 0xe1, 0x80, 0x60}}, // Cities
 };
 
-struct _LoadTileData {
-	GritsPluginMap *map;
-	GritsTile      *tile;
-	guint8         *pixels;
-	gboolean        alpha;
-	gint            width;
-	gint            height;
-};
-static gboolean _load_tile_cb(gpointer _data)
-{
-	struct _LoadTileData *data = _data;
-	g_debug("GritsPluginMap: _load_tile_cb start");
-	if (data->map->aborted) {
-		g_debug("GritsPluginMap: _load_tile - aborted");
-		return FALSE;
-	}
-
-	guint *tex = g_new0(guint, 1);
-	glGenTextures(1, tex);
-	glBindTexture(GL_TEXTURE_2D, *tex);
-
-	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-	glPixelStorei(GL_PACK_ALIGNMENT, 1);
-	glTexImage2D(GL_TEXTURE_2D, 0, 4, data->width, data->height, 0,
-			(data->alpha ? GL_RGBA : GL_RGB), GL_UNSIGNED_BYTE, data->pixels);
-	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-	glFlush();
-
-	data->tile->data = tex;
-	if (data->map->viewer)
-		gtk_widget_queue_draw(GTK_WIDGET(data->map->viewer));
-	g_free(data->pixels);
-	g_free(data);
-	return FALSE;
-}
-
 static void _load_tile(GritsTile *tile, gpointer _map)
 {
 	GritsPluginMap *map = _map;
@@ -108,52 +70,31 @@ static void _load_tile(GritsTile *tile, gpointer _map)
 	}
 	g_free(path);
 
-	/* Copy pixbuf data for callback */
-	struct _LoadTileData *data = g_new0(struct _LoadTileData, 1);
-	data->map    = map;
-	data->tile   = tile;
-	data->pixels = gdk_pixbuf_get_pixels(pixbuf);
-	data->alpha  = gdk_pixbuf_get_has_alpha(pixbuf);
-	data->width  = gdk_pixbuf_get_width(pixbuf);
-	data->height = gdk_pixbuf_get_height(pixbuf);
-	data->pixels = g_memdup(data->pixels,
-			data->width * data->height * (data->alpha ? 4 : 3));
-	g_object_unref(pixbuf);
-
+#ifdef MAP_MAP_COLORS
 	/* Map texture colors, if needed */
-	for (int i = 0; i < data->width * data->height; i++) {
+	gint    width  = gdk_pixbuf_get_width(pixbuf);
+	gint    height = gdk_pixbuf_get_height(pixbuf);
+	guchar *pixels = gdk_pixbuf_get_pixels(pixbuf);
+	for (int i = 0; i < width * height; i++) {
 		for (int j = 0; j < G_N_ELEMENTS(colormap); j++) {
-			if (data->pixels[i*4+0] == colormap[j][0][0] &&
-			    data->pixels[i*4+1] == colormap[j][0][1] &&
-			    data->pixels[i*4+2] == colormap[j][0][2]) {
-				data->pixels[i*4+0] = colormap[j][1][0];
-				data->pixels[i*4+1] = colormap[j][1][1];
-				data->pixels[i*4+2] = colormap[j][1][2];
-				data->pixels[i*4+3] = colormap[j][1][3];
+			if (pixels[i*4+0] == colormap[j][0][0] &&
+			    pixels[i*4+1] == colormap[j][0][1] &&
+			    pixels[i*4+2] == colormap[j][0][2]) {
+				pixels[i*4+0] = colormap[j][1][0];
+				pixels[i*4+1] = colormap[j][1][1];
+				pixels[i*4+2] = colormap[j][1][2];
+				pixels[i*4+3] = colormap[j][1][3];
 				break;
 			}
 		}
 	}
+#endif
 
 	/* Load the GL texture from the main thread */
-	g_idle_add_full(G_PRIORITY_LOW, _load_tile_cb, data, NULL);
+	grits_tile_load_pixbuf(tile, pixbuf);
 	g_debug("GritsPluginMap: _load_tile end %p", g_thread_self());
 }
 
-static gboolean _free_tile_cb(gpointer data)
-{
-	glDeleteTextures(1, data);
-	g_free(data);
-	return FALSE;
-}
-static void _free_tile(GritsTile *tile, gpointer _map)
-{
-	if (tile->data) {
-		g_debug("GritsPluginMap: _free_tile: %p", tile->data);
-		g_idle_add_full(G_PRIORITY_LOW, _free_tile_cb, tile->data, NULL);
-	}
-}
-
 static void _update_tiles(gpointer _, gpointer _map)
 {
 	g_debug("GritsPluginMap: _update_tiles");
@@ -163,8 +104,7 @@ static void _update_tiles(gpointer _, gpointer _map)
 	grits_tile_update(map->tiles, &eye,
 			MAX_RESOLUTION, TILE_WIDTH, TILE_WIDTH,
 			_load_tile, map);
-	grits_tile_gc(map->tiles, time(NULL)-10,
-			_free_tile, map);
+	grits_tile_gc(map->tiles, time(NULL)-10, NULL, map);
 }
 
 /*************
@@ -252,8 +192,6 @@ static void grits_plugin_map_dispose(GObject *gobject)
 		soup_session_abort(map->tms->http->soup);
 		//soup_session_abort(map->wms->http->soup);
 		g_thread_pool_free(map->threads, TRUE, TRUE);
-		while (gtk_events_pending())
-			gtk_main_iteration();
 		g_object_unref(viewer);
 	}
 	G_OBJECT_CLASS(grits_plugin_map_parent_class)->dispose(gobject);
@@ -265,7 +203,7 @@ static void grits_plugin_map_finalize(GObject *gobject)
 	/* Free data */
 	grits_tms_free(map->tms);
 	//grits_wms_free(map->wms);
-	grits_tile_free(map->tiles, _free_tile, map);
+	grits_tile_free(map->tiles, NULL, map);
 	G_OBJECT_CLASS(grits_plugin_map_parent_class)->finalize(gobject);
 
 }
diff --git a/src/plugins/sat.c b/src/plugins/sat.c
index 8fe6e09..b43e4fa 100644
--- a/src/plugins/sat.c
+++ b/src/plugins/sat.c
@@ -24,6 +24,7 @@
  */
 
 #include <time.h>
+#include <string.h>
 #include <glib/gstdio.h>
 
 #include <grits.h>
@@ -34,44 +35,6 @@
 #define TILE_WIDTH     1024
 #define TILE_HEIGHT    512
 
-struct _LoadTileData {
-	GritsPluginSat *sat;
-	GritsTile      *tile;
-	guint8         *pixels;
-	gboolean        alpha;
-	gint            width;
-	gint            height;
-};
-static gboolean _load_tile_cb(gpointer _data)
-{
-	struct _LoadTileData *data = _data;
-	g_debug("GritsPluginSat: _load_tile_cb start");
-	if (data->sat->aborted) {
-		g_debug("GritsPluginSat: _load_tile - aborted");
-		return FALSE;
-	}
-
-	guint *tex = g_new0(guint, 1);
-	glGenTextures(1, tex);
-	glBindTexture(GL_TEXTURE_2D, *tex);
-
-	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-	glPixelStorei(GL_PACK_ALIGNMENT, 1);
-	glTexImage2D(GL_TEXTURE_2D, 0, 4, data->width, data->height, 0,
-			(data->alpha ? GL_RGBA : GL_RGB), GL_UNSIGNED_BYTE, data->pixels);
-	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-	glFlush();
-
-	data->tile->data = tex;
-	gtk_widget_queue_draw(GTK_WIDGET(data->sat->viewer));
-	g_free(data->pixels);
-	g_free(data);
-	return FALSE;
-}
-
 static void _load_tile(GritsTile *tile, gpointer _sat)
 {
 	GritsPluginSat *sat = _sat;
@@ -95,48 +58,28 @@ static void _load_tile(GritsTile *tile, gpointer _sat)
 	}
 	g_free(path);
 
-	/* Copy pixbuf data for callback */
-	struct _LoadTileData *data = g_new0(struct _LoadTileData, 1);
-	data->sat    = sat;
-	data->tile   = tile;
-	data->pixels = gdk_pixbuf_get_pixels(pixbuf);
-	data->alpha  = gdk_pixbuf_get_has_alpha(pixbuf);
-	data->width  = gdk_pixbuf_get_width(pixbuf);
-	data->height = gdk_pixbuf_get_height(pixbuf);
-	data->pixels = g_memdup(data->pixels,
-			data->width * data->height * (data->alpha ? 4 : 3));
-	g_object_unref(pixbuf);
-
 	/* Draw a border */
-	//gint border = 10;
-	//gint stride = gdk_pixbuf_get_rowstride(pixbuf);
-	//for (int i = 0; i < border; i++) {
-	//	memset(&pixels[(       i)*stride], 0xff, stride);
-	//	memset(&pixels[(height-i)*stride], 0xff, stride);
-	//}
-	//for (int i = 0; i < height; i++) {
-	//	memset(&pixels[(i*stride)], 0xff, border*4);
-	//	memset(&pixels[(i*stride)+((width-border)*4)], 0xff, border*4);
-	//}
+#ifdef DRAW_TILE_BORDER
+	gint    border = 10;
+	gint    width  = gdk_pixbuf_get_width(pixbuf);
+	gint    height = gdk_pixbuf_get_height(pixbuf);
+	gint    stride = gdk_pixbuf_get_rowstride(pixbuf);
+	guchar *pixels = gdk_pixbuf_get_pixels(pixbuf);
+	for (int i = 0; i < border; i++) {
+		memset(&pixels[(         i)*stride], 0xff, stride);
+		memset(&pixels[(height-1-i)*stride], 0xff, stride);
+	}
+	for (int i = 0; i < height; i++) {
+		memset(&pixels[(i*stride)                   ], 0xff, border*4);
+		memset(&pixels[(i*stride)+((width-border)*4)], 0xff, border*4);
+	}
+#endif
 
 	/* Load the GL texture from the main thread */
-	g_idle_add_full(G_PRIORITY_LOW, _load_tile_cb, data, NULL);
+	grits_tile_load_pixbuf(tile, pixbuf);
 	g_debug("GritsPluginSat: _load_tile end %p", g_thread_self());
 }
 
-static gboolean _free_tile_cb(gpointer data)
-{
-	glDeleteTextures(1, data);
-	g_free(data);
-	return FALSE;
-}
-static void _free_tile(GritsTile *tile, gpointer _sat)
-{
-	g_debug("GritsPluginSat: _free_tile: %p", tile->data);
-	if (tile->data)
-		g_idle_add_full(G_PRIORITY_LOW, _free_tile_cb, tile->data, NULL);
-}
-
 static void _update_tiles(gpointer _, gpointer _sat)
 {
 	g_debug("GritsPluginSat: _update_tiles");
@@ -146,8 +89,7 @@ static void _update_tiles(gpointer _, gpointer _sat)
 	grits_tile_update(sat->tiles, &eye,
 			MAX_RESOLUTION, TILE_WIDTH, TILE_WIDTH,
 			_load_tile, sat);
-	grits_tile_gc(sat->tiles, time(NULL)-10,
-			_free_tile, sat);
+	grits_tile_gc(sat->tiles, time(NULL)-10, NULL, sat);
 }
 
 /*************
@@ -229,8 +171,6 @@ static void grits_plugin_sat_dispose(GObject *gobject)
 		g_object_unref(sat->tiles);
 		soup_session_abort(sat->wms->http->soup);
 		g_thread_pool_free(sat->threads, TRUE, TRUE);
-		while (gtk_events_pending())
-			gtk_main_iteration();
 		g_object_unref(viewer);
 	}
 	G_OBJECT_CLASS(grits_plugin_sat_parent_class)->dispose(gobject);
@@ -241,7 +181,7 @@ static void grits_plugin_sat_finalize(GObject *gobject)
 	GritsPluginSat *sat = GRITS_PLUGIN_SAT(gobject);
 	/* Free data */
 	grits_wms_free(sat->wms);
-	grits_tile_free(sat->tiles, _free_tile, sat);
+	grits_tile_free(sat->tiles, NULL, sat);
 	G_OBJECT_CLASS(grits_plugin_sat_parent_class)->finalize(gobject);
 
 }



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