[libchamplain] Perform tile creation in idle function
- From: Jiří Techet <jiritechet src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libchamplain] Perform tile creation in idle function
- Date: Wed, 7 Aug 2013 11:37:41 +0000 (UTC)
commit 4ca95de2a62495b93a9e4fdd74f9b8e4c0a12f7b
Author: Jiří Techet <techet gmail com>
Date: Tue Aug 6 11:42:55 2013 +0200
Perform tile creation in idle function
Move tile creation, addition to the viewport and positioning into
idle functions to perform smaller amount of work in the load_visible_tiles()
method which leads to smoother animation because tile loading is better
interleaved with the panning animation.
champlain/champlain-view.c | 187 ++++++++++++++++++++++++++++----------------
1 files changed, 119 insertions(+), 68 deletions(-)
---
diff --git a/champlain/champlain-view.c b/champlain/champlain-view.c
index 6308ec0..de75c71 100644
--- a/champlain/champlain-view.c
+++ b/champlain/champlain-view.c
@@ -130,8 +130,12 @@ typedef struct
typedef struct
{
- ChamplainTile *tile;
+ ChamplainView *view;
ChamplainMapSource *map_source;
+ gint x;
+ gint y;
+ gint zoom_level;
+ gint size;
} FillTileCallbackData;
@@ -189,6 +193,13 @@ struct _ChamplainViewPrivate
gdouble zoom_actor_viewport_x;
gdouble zoom_actor_viewport_y;
guint zoom_actor_timeout;
+
+ GHashTable *tile_map;
+
+ gint tile_x_first;
+ gint tile_y_first;
+ gint tile_x_last;
+ gint tile_y_last;
};
G_DEFINE_TYPE (ChamplainView, champlain_view, CLUTTER_TYPE_ACTOR);
@@ -232,7 +243,6 @@ static void champlain_view_go_to_with_duration (ChamplainView *view,
gdouble latitude,
gdouble longitude,
guint duration);
-static gboolean fill_tile_cb (FillTileCallbackData *data);
static gboolean redraw_timeout_cb(gpointer view);
static void remove_all_tiles (ChamplainView *view);
@@ -593,6 +603,12 @@ champlain_view_dispose (GObject *object)
priv->zoom_actor_timeout = 0;
}
+ if (priv->tile_map != NULL)
+ {
+ g_hash_table_destroy (priv->tile_map);
+ priv->tile_map = NULL;
+ }
+
priv->map_layer = NULL;
priv->license_actor = NULL;
priv->user_layers = NULL;
@@ -991,6 +1007,13 @@ view_size_changed_cb (ChamplainView *view,
}
+static void
+slice_free_gint64 (gpointer data)
+{
+ g_slice_free (gint64, data);
+}
+
+
static void
champlain_view_init (ChamplainView *view)
{
@@ -1037,6 +1060,7 @@ champlain_view_init (ChamplainView *view)
priv->location_updated = FALSE;
priv->redraw_timeout = 0;
priv->zoom_actor_timeout = 0;
+ priv->tile_map = g_hash_table_new_full (g_int64_hash, g_int64_equal, slice_free_gint64, NULL);
clutter_actor_set_background_color (CLUTTER_ACTOR (view), &color);
@@ -1796,6 +1820,72 @@ fill_background_tiles (ChamplainView *view)
}
+static void
+tile_map_set (ChamplainView *view, gint tile_x, gint tile_y, gboolean value)
+{
+ ChamplainViewPrivate *priv = view->priv;
+ gint64 count = champlain_map_source_get_column_count (priv->map_source, priv->zoom_level);
+ gint64 *key = g_slice_alloc (sizeof(gint64));
+ *key = (gint64)tile_y * count + tile_x;
+ if (value)
+ g_hash_table_insert (priv->tile_map, key, GINT_TO_POINTER (TRUE));
+ else
+ g_hash_table_remove (priv->tile_map, key);
+}
+
+
+static gboolean
+tile_in_tile_map (ChamplainView *view, gint tile_x, gint tile_y)
+{
+ ChamplainViewPrivate *priv = view->priv;
+ gint64 count = champlain_map_source_get_column_count (priv->map_source, priv->zoom_level);
+ gint64 key = (gint64)tile_y * count + tile_x;
+ return GPOINTER_TO_INT (g_hash_table_lookup (priv->tile_map, &key));
+}
+
+
+static gboolean
+fill_tile_cb (FillTileCallbackData *data)
+{
+ DEBUG_LOG ()
+
+ ChamplainView *view = data->view;
+ ChamplainViewPrivate *priv = view->priv;
+ ChamplainMapSource *map_source = data->map_source;
+ gint x = data->x;
+ gint y = data->y;
+ gint size = data->size;
+ gint zoom_level = data->zoom_level;
+
+ if (!tile_in_tile_map (view, x, y) && zoom_level == priv->zoom_level && map_source == priv->map_source &&
+ y >= priv->tile_y_first && y < priv->tile_y_last && x >= priv->tile_x_first && x < priv->tile_x_last)
+ {
+ ChamplainTile *tile = champlain_tile_new ();
+
+ champlain_tile_set_x (tile, x);
+ champlain_tile_set_y (tile, y);
+ champlain_tile_set_zoom_level (tile, zoom_level);
+ champlain_tile_set_size (tile, size);
+
+ g_signal_connect (tile, "notify::state", G_CALLBACK (tile_state_notify), view);
+ clutter_actor_add_child (priv->map_layer, CLUTTER_ACTOR (tile));
+ champlain_viewport_set_actor_position (CHAMPLAIN_VIEWPORT (priv->viewport), CLUTTER_ACTOR (tile), x *
size, y * size);
+
+ /* updates champlain_view state automatically as
+ notify::state signal is connected */
+ champlain_tile_set_state (tile, CHAMPLAIN_STATE_LOADING);
+
+ champlain_map_source_fill_tile (priv->map_source, tile);
+ tile_map_set (view, x, y, TRUE);
+ }
+
+ g_object_unref (view);
+ g_slice_free (FillTileCallbackData, data);
+
+ return FALSE;
+}
+
+
static void
load_visible_tiles (ChamplainView *view,
gboolean relocate)
@@ -1806,11 +1896,10 @@ load_visible_tiles (ChamplainView *view,
ClutterActorIter iter;
gint size;
ClutterActor *child;
- gint x_count, y_count, x_first, y_first, x_end, y_end, max_x_end, max_y_end;
- gboolean *tile_map;
+ gint x_count, y_count, max_x_end, max_y_end;
gint arm_size, arm_max, turn;
gint dirs[5] = { 0, 1, 0, -1, 0 };
- int i, x, y;
+ gint i, x, y;
size = champlain_map_source_get_tile_size (priv->map_source);
@@ -1820,21 +1909,19 @@ load_visible_tiles (ChamplainView *view,
x_count = ceil ((gfloat) priv->viewport_width / size) + 1;
y_count = ceil ((gfloat) priv->viewport_height / size) + 1;
- x_first = CLAMP (priv->viewport_x / size, 0, max_x_end);
- y_first = CLAMP (priv->viewport_y / size, 0, max_y_end);
-
- x_end = x_first + x_count;
- y_end = y_first + y_count;
+ priv->tile_x_first = CLAMP (priv->viewport_x / size, 0, max_x_end);
+ priv->tile_y_first = CLAMP (priv->viewport_y / size, 0, max_y_end);
- x_end = CLAMP (x_end, x_first, max_x_end);
- y_end = CLAMP (y_end, y_first, max_y_end);
+ priv->tile_x_last = priv->tile_x_first + x_count;
+ priv->tile_y_last = priv->tile_y_first + y_count;
- x_count = x_end - x_first;
- y_count = y_end - y_first;
+ priv->tile_x_last = CLAMP (priv->tile_x_last, priv->tile_x_first, max_x_end);
+ priv->tile_y_last = CLAMP (priv->tile_y_last, priv->tile_y_first, max_y_end);
- DEBUG ("Range %d, %d to %d, %d", x_first, y_first, x_end, y_end);
+ x_count = priv->tile_x_last - priv->tile_x_first;
+ y_count = priv->tile_y_last - priv->tile_y_first;
- tile_map = g_slice_alloc0 (sizeof (gboolean) * x_count * y_count);
+ DEBUG ("Range %d, %d to %d, %d", priv->tile_x_first, priv->tile_y_first, priv->tile_x_last,
priv->tile_y_last);
/* fill background tiles */
if (priv->background_content != NULL)
@@ -1849,24 +1936,20 @@ load_visible_tiles (ChamplainView *view,
gint tile_x = champlain_tile_get_x (tile);
gint tile_y = champlain_tile_get_y (tile);
- if (tile_x < x_first || tile_x >= x_end ||
- tile_y < y_first || tile_y >= y_end)
+ if (tile_x < priv->tile_x_first || tile_x >= priv->tile_x_last ||
+ tile_y < priv->tile_y_first || tile_y >= priv->tile_y_last)
{
- /* inform map source to terminate loading the tile */
champlain_tile_set_state (tile, CHAMPLAIN_STATE_DONE);
clutter_actor_iter_destroy (&iter);
+ tile_map_set (view, tile_x, tile_y, FALSE);
}
- else
- {
- tile_map[(tile_y - y_first) * x_count + (tile_x - x_first)] = TRUE;
- if (relocate)
- champlain_viewport_set_actor_position (CHAMPLAIN_VIEWPORT (priv->viewport), CLUTTER_ACTOR
(tile), tile_x * size, tile_y * size);
- }
+ else if (relocate)
+ champlain_viewport_set_actor_position (CHAMPLAIN_VIEWPORT (priv->viewport), CLUTTER_ACTOR (tile),
tile_x * size, tile_y * size);
}
-
+
/* Load new tiles if needed */
- x = x_first + x_count / 2 - 1;
- y = y_first + y_count / 2 - 1;
+ x = priv->tile_x_first + x_count / 2 - 1;
+ y = priv->tile_y_first + y_count / 2 - 1;
arm_max = MAX (x_count, y_count) + 2;
arm_size = 1;
@@ -1874,33 +1957,19 @@ load_visible_tiles (ChamplainView *view,
{
for (i = 0; i < arm_size; i++)
{
- if (y >= y_first && y < y_end && x >= x_first && x < x_end &&
- !tile_map[(y - y_first) * x_count + (x - x_first)])
+ if (!tile_in_tile_map (view, x, y) && y >= priv->tile_y_first && y < priv->tile_y_last && x >=
priv->tile_x_first && x < priv->tile_x_last)
{
- ChamplainTile *tile;
FillTileCallbackData *data;
DEBUG ("Loading tile %d, %d, %d", priv->zoom_level, x, y);
- tile = champlain_tile_new ();
- champlain_tile_set_x (tile, x);
- champlain_tile_set_y (tile, y);
- champlain_tile_set_zoom_level (tile, priv->zoom_level);
- champlain_tile_set_size (tile, size);
-
- g_signal_connect (tile, "notify::state", G_CALLBACK (tile_state_notify), view);
- clutter_actor_add_child (priv->map_layer, CLUTTER_ACTOR (tile));
- champlain_viewport_set_actor_position (CHAMPLAIN_VIEWPORT (priv->viewport), CLUTTER_ACTOR
(tile), x * size, y * size);
-
- /* updates champlain_view state automatically as
- notify::state signal is connected */
- champlain_tile_set_state (tile, CHAMPLAIN_STATE_LOADING);
data = g_slice_new (FillTileCallbackData);
- data->tile = tile;
+ data->x = x;
+ data->y = y;
+ data->size = size;
+ data->zoom_level = priv->zoom_level;
data->map_source = priv->map_source;
-
- g_object_ref (tile);
- g_object_ref (priv->map_source);
+ data->view = g_object_ref (view);
g_idle_add_full (CLUTTER_PRIORITY_REDRAW, (GSourceFunc) fill_tile_cb, data, NULL);
}
@@ -1912,26 +1981,6 @@ load_visible_tiles (ChamplainView *view,
if (turn % 2 == 1)
arm_size++;
}
-
- g_slice_free1 (sizeof (gboolean) * x_count * y_count, tile_map);
-}
-
-
-static gboolean
-fill_tile_cb (FillTileCallbackData *data)
-{
- DEBUG_LOG ()
-
- ChamplainTile *tile = data->tile;
- ChamplainMapSource *map_source = data->map_source;
-
- champlain_map_source_fill_tile (map_source, tile);
-
- g_slice_free (FillTileCallbackData, data);
- g_object_unref (map_source);
- g_object_unref (tile);
-
- return FALSE;
}
@@ -1950,6 +1999,8 @@ remove_all_tiles (ChamplainView *view)
while (clutter_actor_iter_next (&iter, &child))
champlain_tile_set_state (CHAMPLAIN_TILE (child), CHAMPLAIN_STATE_DONE);
+ g_hash_table_remove_all (priv->tile_map);
+
clutter_actor_destroy_all_children (priv->map_layer);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]