]> Pileus Git - grits/commitdiff
Move low level tile loading to GritsTile
authorAndy Spencer <andy753421@gmail.com>
Thu, 27 Dec 2012 03:23:01 +0000 (03:23 +0000)
committerAndy Spencer <andy753421@gmail.com>
Thu, 27 Dec 2012 03:23:01 +0000 (03:23 +0000)
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
src/objects/grits-tile.h
src/plugins/elev.c
src/plugins/map.c
src/plugins/sat.c

index 6ea70f88cbf052e38073b8087e3ea300c7f19c79..b903492332ace5c5e0908f0d402a00c6dc66a4bf 100644 (file)
@@ -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;
@@ -246,6 +246,99 @@ void grits_tile_update(GritsTile *tile, GritsPoint *eye,
                                load_func, user_data);
 }
 
+/**
+ * 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
@@ -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;
index b13e1c346c62b9b0b86af471bbcc1c52b2e52a0e..fc87695ab3718f43de5dd5dde8c6963232930c3b 100644 (file)
@@ -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);
 
index db7b9775e535650cd16c3c91be774c154ad385a2..3f7b2a195e763e567c89f39bc4a7a73d85968bbc 100644 (file)
 #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);
 
 }
index 13f986c10e5dd2dbdc22245ff03d0a09483c1408..a573dcbf4b085518951e33268cc4759ff7685f0b 100644 (file)
 #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);
 
 }
index 8fe6e091ab27a3de2bd2807b8ceeab12cf6e9c81..b43e4faf1ccbfd13c7d99615478206b79de223d1 100644 (file)
@@ -24,6 +24,7 @@
  */
 
 #include <time.h>
+#include <string.h>
 #include <glib/gstdio.h>
 
 #include <grits.h>
 #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);
 
 }