]> Pileus Git - aweather/commitdiff
Move gdk_pixbuf calls to main thread
authorAndy Spencer <andy753421@gmail.com>
Mon, 3 May 2010 07:44:49 +0000 (07:44 +0000)
committerAndy Spencer <andy753421@gmail.com>
Mon, 3 May 2010 07:44:49 +0000 (07:44 +0000)
Hopefully this will fix some Win32 issues

src/plugins/radar.c

index ecdd22bd525052b1a5d143f165c40ade0f9976c1..1bf2de2978364b5ebbfe5e5e05ad43a13df33495 100644 (file)
@@ -344,11 +344,10 @@ struct _RadarConus {
        GtkWidget   *config;
        time_t       time;
        const gchar *message;
-       gchar       *nearest;
 
+       gchar       *path;
        GisTile     *tile[2];
        gpointer    *tile_ref[2];
-       guchar      *pixels[2];
 
        guint        time_id;     // "time-changed"     callback ID
        guint        refresh_id;  // "refresh"          callback ID
@@ -367,47 +366,109 @@ void _conus_update_loading(gchar *file, goffset cur,
        g_free(msg);
 }
 
+/* Copy images to graphics memory */
+static void _conus_update_end_copy(GisTile *tile, guchar *pixels)
+{
+       if (!tile->data) {
+               tile->data = g_new0(guint, 1);
+               glGenTextures(1, tile->data);
+       }
+
+       guint *tex = tile->data;
+       glBindTexture(GL_TEXTURE_2D, *tex);
+
+       glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+       glPixelStorei(GL_PACK_ALIGNMENT, 1);
+       glTexImage2D(GL_TEXTURE_2D, 0, 4, 2048, 2048, 0,
+                       GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+       glTexSubImage2D(GL_TEXTURE_2D, 0, 1,1, CONUS_WIDTH/2,CONUS_HEIGHT,
+                       GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+       tile->coords.n = 1.0/(CONUS_WIDTH/2);
+       tile->coords.w = 1.0/ CONUS_HEIGHT;
+       tile->coords.s = tile->coords.n +  CONUS_HEIGHT   / 2048.0;
+       tile->coords.e = tile->coords.w + (CONUS_WIDTH/2) / 2048.0;
+       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);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+       glFlush();
+}
+
+/* Split the pixbuf into east and west halves (with 2K sides)
+ * Also map the pixbuf's alpha values */
+static void _conus_update_end_split(guchar *pixels, guchar *west, guchar *east,
+               gint width, gint height, gint pxsize)
+{
+       g_debug("GisPluginRadar: _conus_update_thread - split");
+       guchar *out[] = {west,east};
+       const guchar alphamap[][4] = {
+               {0x04, 0xe9, 0xe7, 0x30},
+               {0x01, 0x9f, 0xf4, 0x60},
+               {0x03, 0x00, 0xf4, 0x90},
+       };
+       for (int y = 0; y < height; y++)
+       for (int x = 0; x < width;  x++) {
+               gint subx = x % (width/2);
+               gint idx  = x / (width/2);
+               guchar *src = &pixels[(y*width+x)*pxsize];
+               guchar *dst = &out[idx][(y*(width/2)+subx)*4];
+               if (src[0] > 0xe0 &&
+                   src[1] > 0xe0 &&
+                   src[2] > 0xe0) {
+                       dst[3] = 0x00;
+               } else {
+                       dst[0] = src[0];
+                       dst[1] = src[1];
+                       dst[2] = src[2];
+                       dst[3] = 0xff;
+                       for (int j = 0; j < G_N_ELEMENTS(alphamap); j++)
+                               if (src[0] == alphamap[j][0] &&
+                                   src[1] == alphamap[j][1] &&
+                                   src[2] == alphamap[j][2])
+                                       dst[3] = alphamap[j][3];
+               }
+       }
+}
+
 gboolean _conus_update_end(gpointer _conus)
 {
        RadarConus *conus = _conus;
        g_debug("GisPluginRadar: _conus_update_end");
 
-       for (int i = 0; i < 2; i++) {
-               GisTile  *tile   = conus->tile[i];
-               guchar   *pixels = conus->pixels[i];
+       /* Check error status */
+       if (conus->message) {
+               g_warning("GisPluginRadar: _conus_update_end - %s", conus->message);
+               _gtk_bin_set_child(GTK_BIN(conus->config), gtk_label_new(conus->message));
+               return FALSE;
+       }
 
-               if (!tile->data) {
-                       tile->data = g_new0(guint, 1);
-                       glGenTextures(1, tile->data);
-               }
+       /* Load and pixbuf */
+       GError *error = NULL;
+       GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(conus->path, &error);
+       guchar    *pixels = gdk_pixbuf_get_pixels(pixbuf);
+       gint       width  = gdk_pixbuf_get_width(pixbuf);
+       gint       height = gdk_pixbuf_get_height(pixbuf);
+       gint       pxsize = gdk_pixbuf_get_has_alpha(pixbuf) ? 4 : 3;
 
-               guint *tex = tile->data;
-               glBindTexture(GL_TEXTURE_2D, *tex);
-
-               glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-               glPixelStorei(GL_PACK_ALIGNMENT, 1);
-               glTexImage2D(GL_TEXTURE_2D, 0, 4, 2048, 2048, 0,
-                               GL_RGBA, GL_UNSIGNED_BYTE, NULL);
-               glTexSubImage2D(GL_TEXTURE_2D, 0, 1,1, CONUS_WIDTH/2,CONUS_HEIGHT,
-                               GL_RGBA, GL_UNSIGNED_BYTE, pixels);
-               tile->coords.n = 1.0/(CONUS_WIDTH/2);
-               tile->coords.w = 1.0/ CONUS_HEIGHT;
-               tile->coords.s = tile->coords.n +  CONUS_HEIGHT   / 2048.0;
-               tile->coords.e = tile->coords.w + (CONUS_WIDTH/2) / 2048.0;
-               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);
-               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
-               glFlush();
-
-               g_free(pixels);
-       }
+       /* Split pixels into east/west parts */
+       guchar *pixels_west = g_malloc(4*(width/2)*height);
+       guchar *pixels_east = g_malloc(4*(width/2)*height);
+       _conus_update_end_split(pixels, pixels_west, pixels_east,
+                       width, height, pxsize);
+       g_object_unref(pixbuf);
 
-       /* finish */
-       _gtk_bin_set_child(GTK_BIN(conus->config),
-                       gtk_label_new(conus->nearest));
+       /* Copy pixels to graphics memory */
+       _conus_update_end_copy(conus->tile[0], pixels_west);
+       _conus_update_end_copy(conus->tile[1], pixels_east);
+       g_free(pixels_west);
+       g_free(pixels_east);
+
+       /* Update GUI */
+       gchar *label = g_path_get_basename(conus->path);
+       _gtk_bin_set_child(GTK_BIN(conus->config), gtk_label_new(label));
        gtk_widget_queue_draw(GTK_WIDGET(conus->viewer));
-       g_free(conus->nearest);
+       g_free(conus->path);
+       g_free(label);
 
        return FALSE;
 }
@@ -415,6 +476,7 @@ gboolean _conus_update_end(gpointer _conus)
 gpointer _conus_update_thread(gpointer _conus)
 {
        RadarConus *conus = _conus;
+       conus->message = NULL;
 
        /* Find nearest */
        g_debug("GisPluginRadar: _conus_update_thread - nearest");
@@ -423,69 +485,26 @@ gpointer _conus_update_thread(gpointer _conus)
        GList *files = gis_http_available(conus->http,
                        "^Conus_[^\"]*_N0Ronly.gif$", "",
                        NULL, (offline ? NULL : conus_url));
-       conus->nearest = _find_nearest(conus->time, files, 6, "%Y%m%d_%H%M");
+       gchar *nearest = _find_nearest(conus->time, files, 6, "%Y%m%d_%H%M");
        g_list_foreach(files, (GFunc)g_free, NULL);
        g_list_free(files);
-       if (!conus->nearest) {
+       if (!nearest) {
                conus->message = "No suitable files";
                goto out;
        }
 
        /* Fetch the image */
        g_debug("GisPluginRadar: _conus_update_thread - fetch");
-       gchar *uri     = g_strconcat(conus_url, conus->nearest, NULL);
-       gchar *path    = gis_http_fetch(conus->http, uri, conus->nearest, GIS_ONCE,
+       gchar *uri  = g_strconcat(conus_url, nearest, NULL);
+       conus->path = gis_http_fetch(conus->http, uri, nearest, GIS_ONCE,
                        _conus_update_loading, conus);
+       g_free(nearest);
        g_free(uri);
-       if (!path) {
+       if (!conus->path) {
                conus->message = "Fetch failed";
                goto out;
        }
 
-       /* Load and split the pixbuf into two 2K data segments */
-       g_debug("GisPluginRadar: _conus_update_thread - load");
-       GError *error = NULL;
-       GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(path, &error);
-       guchar    *pixels = gdk_pixbuf_get_pixels(pixbuf);
-       gint       width  = gdk_pixbuf_get_width(pixbuf);
-       gint       height = gdk_pixbuf_get_height(pixbuf);
-       gint       pxsize = gdk_pixbuf_get_has_alpha(pixbuf) ? 4 : 3;
-       g_free(path);
-
-       /* Split the pixbuf into east and west halves (with 2K sides)
-        * Also map the pixbuf's alpha values */
-       g_debug("GisPluginRadar: _conus_update_thread - split");
-       conus->pixels[0] = g_malloc(4*(width/2)*height);
-       conus->pixels[1] = g_malloc(4*(width/2)*height);
-       const guchar alphamap[][4] = {
-               {0x04, 0xe9, 0xe7, 0x30},
-               {0x01, 0x9f, 0xf4, 0x60},
-               {0x03, 0x00, 0xf4, 0x90},
-       };
-       for (int y = 0; y < height; y++)
-       for (int x = 0; x < width;  x++) {
-               gint subx = x % (width/2);
-               gint idx  = x / (width/2);
-               guchar *src = &pixels[(y*width+x)*pxsize];
-               guchar *dst = &conus->pixels[idx][(y*(width/2)+subx)*4];
-               if (src[0] > 0xe0 &&
-                   src[1] > 0xe0 &&
-                   src[2] > 0xe0) {
-                       dst[3] = 0x00;
-               } else {
-                       dst[0] = src[0];
-                       dst[1] = src[1];
-                       dst[2] = src[2];
-                       dst[3] = 0xff;
-                       for (int j = 0; j < G_N_ELEMENTS(alphamap); j++)
-                               if (src[0] == alphamap[j][0] &&
-                                   src[1] == alphamap[j][1] &&
-                                   src[2] == alphamap[j][2])
-                                       dst[3] = alphamap[j][3];
-               }
-       }
-       g_object_unref(pixbuf);
-
 out:
        g_debug("GisPluginRadar: _conus_update_thread - done");
        g_idle_add(_conus_update_end, conus);