Complete.Org: Mailing Lists: Archives: freeciv-dev: February 2005:
[Freeciv-Dev] (PR#12269) two new tile update types
Home

[Freeciv-Dev] (PR#12269) two new tile update types

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] (PR#12269) two new tile update types
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Tue, 15 Feb 2005 22:25:19 -0800
Reply-to: bugs@xxxxxxxxxxx

<URL: http://bugs.freeciv.org/Ticket/Display.html?id=12269 >

This preliminary patch adds and uses two new tile update types.

- A single-tile update has just the basic tile area.  It's small and 
fast.  This should be used for gotos (and makes them somewhat faster)

- A city-desc update updates the description for the city on a tile. 
This is used inside update_city_description, naturally.  It should make 
end-of-turn updates reasonably faster.

This is a superset of PR#12268.

-jason

Index: client/climisc.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/climisc.c,v
retrieving revision 1.152
diff -u -r1.152 climisc.c
--- client/climisc.c    15 Feb 2005 16:40:40 -0000      1.152
+++ client/climisc.c    16 Feb 2005 06:23:10 -0000
@@ -71,6 +71,7 @@
   struct tile *ptile = punit->tile;
   int hc = punit->homecity;
   struct unit *ufocus = get_unit_in_focus();
+  struct unit old_unit = *punit;
 
   freelog(LOG_DEBUG, "removing unit %d, %s %s (%d %d) hcity %d",
          punit->id, get_nation_name(unit_owner(punit)->nation),
@@ -114,7 +115,7 @@
            TILE_XY(pcity->tile));
   }
 
-  refresh_tile_mapcanvas(ptile, FALSE);
+  refresh_unit_mapcanvas(&old_unit, ptile, TRUE, FALSE);
 }
 
 /**************************************************************************
@@ -124,6 +125,7 @@
 {
   bool effect_update;
   struct tile *ptile = pcity->tile;
+  struct city old_city = *pcity;
 
   freelog(LOG_DEBUG, "removing city %s, %s, (%d %d)", pcity->name,
          get_nation_name(city_owner(pcity)->nation), TILE_XY(ptile));
@@ -144,7 +146,7 @@
   popdown_city_dialog(pcity);
   game_remove_city(pcity);
   city_report_dialog_update();
-  refresh_tile_mapcanvas(ptile, FALSE);
+  refresh_city_mapcanvas(&old_city, ptile, TRUE, FALSE);
 }
 
 /**************************************************************************
Index: client/control.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/control.c,v
retrieving revision 1.158
diff -u -r1.158 control.c
--- client/control.c    15 Feb 2005 16:40:40 -0000      1.158
+++ client/control.c    16 Feb 2005 06:23:10 -0000
@@ -168,7 +168,7 @@
     auto_center_on_focus_unit();
 
     punit->focus_status=FOCUS_AVAIL;
-    refresh_unit_mapcanvas(punit, punit->tile, FALSE);
+    refresh_unit_mapcanvas(punit, punit->tile, TRUE, FALSE);
 
     if (unit_has_orders(punit)) {
       /* Clear the focus unit's orders. */
@@ -184,7 +184,8 @@
   /* avoid the old focus unit disappearing: */
   if (punit_old_focus
       && (!punit || !same_pos(punit_old_focus->tile, punit->tile))) {
-    refresh_unit_mapcanvas(punit_old_focus, punit_old_focus->tile, FALSE);
+    refresh_unit_mapcanvas(punit_old_focus, punit_old_focus->tile,
+                          TRUE, FALSE);
   }
 
   update_unit_info_label(punit);
@@ -422,7 +423,14 @@
       /* If we lag, we don't try to catch up.  Instead we just start a
        * new blink_time on every update. */
       blink_timer = renew_timer_start(blink_timer, TIMER_USER, TIMER_ACTIVE);
-      refresh_unit_mapcanvas(punit, punit->tile, TRUE);
+
+      /* HACK: since this is called so often we're careful to only do the
+       * minimal refresh. */
+      if (sprites.unit.select[0]) {
+       refresh_tile_mapcanvas(punit->tile, FALSE, TRUE);
+      } else {
+       refresh_unit_mapcanvas(punit, punit->tile, FALSE, TRUE);
+      }
     }
 
     return blink_time - read_timer_seconds(blink_timer);
@@ -1427,7 +1435,7 @@
   if (punit->transported_by == -1) {
     /* We have to refresh the tile before moving.  This will draw
      * the tile without the unit (because it was unlinked above). */
-    refresh_unit_mapcanvas(punit, ptile, FALSE);
+    refresh_unit_mapcanvas(punit, ptile, TRUE, FALSE);
 
     if (do_animation) {
       int dx, dy;
Index: client/goto.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/goto.c,v
retrieving revision 1.81
diff -u -r1.81 goto.c
--- client/goto.c       5 Feb 2005 07:41:53 -0000       1.81
+++ client/goto.c       16 Feb 2005 06:23:11 -0000
@@ -210,8 +210,8 @@
   }
 
   /* Refresh tiles so turn information is shown. */
-  refresh_tile_mapcanvas(old_tile, FALSE);
-  refresh_tile_mapcanvas(ptile, FALSE);
+  refresh_tile_mapcanvas(old_tile, FALSE, FALSE);
+  refresh_tile_mapcanvas(ptile, FALSE, FALSE);
 }
 
 /********************************************************************** 
Index: client/mapctrl_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapctrl_common.c,v
retrieving revision 1.47
diff -u -r1.47 mapctrl_common.c
--- client/mapctrl_common.c     15 Feb 2005 16:40:40 -0000      1.47
+++ client/mapctrl_common.c     16 Feb 2005 06:23:11 -0000
@@ -294,7 +294,7 @@
     return;
   }
 
-  refresh_tile_mapcanvas(ptile, TRUE);
+  refresh_tile_mapcanvas(ptile, FALSE, TRUE);
 }
 
 /**************************************************************************
Index: client/mapview_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.c,v
retrieving revision 1.190
diff -u -r1.190 mapview_common.c
--- client/mapview_common.c     16 Feb 2005 04:46:09 -0000      1.190
+++ client/mapview_common.c     16 Feb 2005 06:23:11 -0000
@@ -66,19 +66,33 @@
   UPDATE_CITY_DESCRIPTIONS = 1,
   UPDATE_MAP_CANVAS_VISIBLE = 2
 };
+
+/* A tile update has a tile associated with it as well as an area type.
+ * See unqueue_mapview_updates for a thorough explanation. */
+enum tile_update_type {
+  TILE_UPDATE_TILE_SINGLE,
+  TILE_UPDATE_TILE_FULL,
+  TILE_UPDATE_UNIT,
+  TILE_UPDATE_CITY_DESC,
+  TILE_UPDATE_CITYMAP,
+  TILE_UPDATE_COUNT
+};
 static void queue_mapview_update(enum update_type update);
-static void queue_mapview_tile_update(struct tile *ptile);
-static void queue_mapview_unit_update(struct unit *punit, struct tile *ptile);
-static void queue_mapview_city_update(struct city *pcity, struct tile *ptile,
-                                     bool full_refresh);
+static void queue_mapview_tile_update(struct tile *ptile,
+                                     enum tile_update_type type);
 static void unqueue_mapview_updates(bool write_to_screen);
 
 /**************************************************************************
  Refreshes a single tile on the map canvas.
 **************************************************************************/
-void refresh_tile_mapcanvas(struct tile *ptile, bool write_to_screen)
+void refresh_tile_mapcanvas(struct tile *ptile,
+                           bool full_refresh, bool write_to_screen)
 {
-  queue_mapview_tile_update(ptile);
+  if (full_refresh) {
+    queue_mapview_tile_update(ptile, TILE_UPDATE_TILE_FULL);
+  } else {
+    queue_mapview_tile_update(ptile, TILE_UPDATE_TILE_SINGLE);
+  }
   if (write_to_screen) {
     unqueue_mapview_updates(TRUE);
   }
@@ -88,9 +102,13 @@
  Refreshes a single unit on the map canvas.
 **************************************************************************/
 void refresh_unit_mapcanvas(struct unit *punit, struct tile *ptile,
-                           bool write_to_screen)
+                           bool full_refresh, bool write_to_screen)
 {
-  queue_mapview_unit_update(punit, ptile);
+  if (full_refresh && unit_type_flag(punit->type, F_CITIES)) {
+    queue_mapview_tile_update(ptile, TILE_UPDATE_CITYMAP);
+  } else {
+    queue_mapview_tile_update(ptile, TILE_UPDATE_UNIT);
+  }
   if (write_to_screen) {
     unqueue_mapview_updates(TRUE);
   }
@@ -105,8 +123,11 @@
 void refresh_city_mapcanvas(struct city *pcity, struct tile *ptile,
                            bool full_refresh, bool write_to_screen)
 {
-  queue_mapview_city_update(pcity, ptile,
-                           full_refresh && (draw_map_grid || draw_borders));
+  if (full_refresh && (draw_map_grid || draw_borders)) {
+    queue_mapview_tile_update(ptile, TILE_UPDATE_CITYMAP);
+  } else {
+    queue_mapview_tile_update(ptile, TILE_UPDATE_UNIT);
+  }
   if (write_to_screen) {
     unqueue_mapview_updates(TRUE);
   }
@@ -1096,7 +1117,7 @@
     color_index = (color_index + 1) % NUM_CITY_COLORS;
   }
 
-  refresh_unit_mapcanvas(punit, punit->tile, FALSE);
+  refresh_unit_mapcanvas(punit, punit->tile, TRUE, FALSE);
 }
 
 /****************************************************************************
@@ -1710,15 +1731,7 @@
 **************************************************************************/
 void update_city_description(struct city *pcity)
 {
-  int canvas_x, canvas_y;
-
-  /* We update the entire map canvas area that this city description
-   * might be covering.  This may, for instance, redraw other city
-   * descriptions that overlap with this one. */
-  (void) tile_to_canvas_pos(&canvas_x, &canvas_y, pcity->tile);
-  update_map_canvas(canvas_x - (max_desc_width - NORMAL_TILE_WIDTH) / 2,
-                   canvas_y + NORMAL_TILE_HEIGHT,
-                   max_desc_width, max_desc_height);
+  queue_mapview_tile_update(pcity->tile, TILE_UPDATE_CITY_DESC);
 }
 
 /**************************************************************************
@@ -1863,8 +1876,8 @@
     assert(0);
     return;
   }
-  refresh_tile_mapcanvas(src_tile, FALSE);
-  refresh_tile_mapcanvas(dst_tile, FALSE);
+  refresh_tile_mapcanvas(src_tile, FALSE, FALSE);
+  refresh_tile_mapcanvas(dst_tile, FALSE, FALSE);
 }
 
 /****************************************************************************
@@ -1888,10 +1901,10 @@
 
     if (myrand(diff0 + diff1) < diff0) {
       punit0->hp--;
-      refresh_unit_mapcanvas(punit0, punit0->tile, FALSE);
+      refresh_unit_mapcanvas(punit0, punit0->tile, FALSE, FALSE);
     } else {
       punit1->hp--;
-      refresh_unit_mapcanvas(punit1, punit1->tile, FALSE);
+      refresh_unit_mapcanvas(punit1, punit1->tile, FALSE, FALSE);
     }
 
     unqueue_mapview_updates(TRUE);
@@ -1903,7 +1916,7 @@
   if (num_tiles_explode_unit > 0
       && tile_to_canvas_pos(&canvas_x, &canvas_y,
                           losing_unit->tile)) {
-    refresh_unit_mapcanvas(losing_unit, losing_unit->tile, FALSE);
+    refresh_unit_mapcanvas(losing_unit, losing_unit->tile, FALSE, FALSE);
     unqueue_mapview_updates(FALSE);
     canvas_copy(mapview.tmp_store, mapview.store,
                canvas_x, canvas_y, canvas_x, canvas_y,
@@ -1935,8 +1948,8 @@
   }
 
   set_units_in_combat(NULL, NULL);
-  refresh_unit_mapcanvas(punit0, punit0->tile, FALSE);
-  refresh_unit_mapcanvas(punit1, punit1->tile, FALSE);
+  refresh_unit_mapcanvas(punit0, punit0->tile, TRUE, FALSE);
+  refresh_unit_mapcanvas(punit1, punit1->tile, TRUE, FALSE);
 }
 
 /**************************************************************************
@@ -2163,9 +2176,7 @@
  * whole citymap area.  A unit update covers just the "full" unit tile
  * area.  A tile update covers the base tile plus half a tile in each
  * direction. */
-struct tile_list *city_updates = NULL;
-struct tile_list *unit_updates = NULL;
-struct tile_list *tile_updates = NULL;
+struct tile_list *tile_updates[TILE_UPDATE_COUNT];
 
 /****************************************************************************
   This callback is called during an idle moment to unqueue any pending
@@ -2213,58 +2224,19 @@
 }
 
 /**************************************************************************
-  Appends a tile to the list.  The list is allocated if NULL.  The (new)
-  list is returned.
-**************************************************************************/
-static struct tile_list *append_tile_to_list(struct tile *ptile,
-                                            struct tile_list *plist)
-{
-  if (!plist) {
-    plist = tile_list_new();
-  }
-  tile_list_append(plist, ptile);
-  return plist;
-}
-
-/**************************************************************************
   Queue this tile to be refreshed.  The refresh will be done some time
   soon thereafter, and grouped with other needed refreshes.
 
   Note this should only be called for tiles.  For cities or units use
   queue_mapview_xxx_update instead.
 **************************************************************************/
-void queue_mapview_tile_update(struct tile *ptile)
-{
-  tile_updates = append_tile_to_list(ptile, tile_updates);
-  queue_add_callback();
-}
-
-/**************************************************************************
-  Queue this unit to be refreshed.  The refresh will be done some time
-  soon thereafter, and grouped with other needed refreshes.
-**************************************************************************/
-void queue_mapview_unit_update(struct unit *punit, struct tile *ptile)
+void queue_mapview_tile_update(struct tile *ptile,
+                              enum tile_update_type type)
 {
-  if (unit_type_flag(punit->type, F_CITIES)) {
-    city_updates = append_tile_to_list(ptile, city_updates);
-  } else {
-    unit_updates = append_tile_to_list(ptile, unit_updates);
-  }
-  queue_add_callback();
-}
-
-/**************************************************************************
-  Queue this city to be refreshed.  The refresh will be done some time
-  soon thereafter, and grouped with other needed refreshes.
-**************************************************************************/
-void queue_mapview_city_update(struct city *pcity, struct tile *ptile,
-                              bool full_refresh)
-{
-  if (full_refresh) {
-    city_updates = append_tile_to_list(ptile, city_updates);
-  } else {
-    unit_updates = append_tile_to_list(ptile, unit_updates);
+  if (!tile_updates[type]) {
+    tile_updates[type] = tile_list_new();
   }
+  tile_list_append(tile_updates[type], ptile);
   queue_add_callback();
 }
 
@@ -2273,6 +2245,37 @@
 **************************************************************************/
 void unqueue_mapview_updates(bool write_to_screen)
 {
+  /* Calculate the area covered by each update type.  The area array gives
+   * the offset from the tile origin as well as the width and height of the
+   * area to be updated.  This is initialized each time when entering the
+   * function from the existing tileset variables.
+   *
+   * A TILE update covers the base tile (W x H) plus a half-tile in each
+   * direction (for edge/corner graphics), making its area 2W x 2H.
+   *
+   * A UNIT update covers a UW x UH area.  This is centered horizontally
+   * over the tile but extends up above the tile (e.g., units in iso-view).
+   *
+   * A CITYMAP update covers the whole citymap of a tile.  This includes
+   * the citymap area itself plus an extra half-tile in each direction (for
+   * edge/corner graphics).
+   */
+  const int W = NORMAL_TILE_WIDTH, H = NORMAL_TILE_HEIGHT;
+  const int UW = UNIT_TILE_WIDTH, UH = UNIT_TILE_HEIGHT;
+  const int city_width = get_citydlg_canvas_width() + W;
+  const int city_height = get_citydlg_canvas_height() + H;
+  const struct {
+    int dx, dy, w, h;
+  } area[TILE_UPDATE_COUNT] = {
+    {0, 0, W, H},
+    {-W / 2, -H / 2, 2 * W, 2 * H},
+    {(W - UW) / 2, H - UH, UW, UH},
+    {-(max_desc_width - W) / 2, H, max_desc_width, max_desc_height},
+    {-(city_width - W) / 2, -(city_height - H) / 2, city_width, city_height}
+  };
+
+  int i;
+
   freelog(LOG_DEBUG, "unqueue_mapview_update: needed_updates=%d",
          needed_updates);
 
@@ -2285,73 +2288,34 @@
     } else {
       int min_x = mapview.width, min_y = mapview.height;
       int max_x = 0, max_y = 0;
+      int i;
 
-      if (tile_updates) {
-       tile_list_iterate(tile_updates, ptile) {
-         int x0, y0, x1, y1;
-
-         if (tile_to_canvas_pos(&x0, &y0, ptile)) {
-           x0 -= NORMAL_TILE_WIDTH / 2;
-           y0 -= NORMAL_TILE_HEIGHT / 2;
-           x1 = x0 + 2 * NORMAL_TILE_WIDTH;
-           y1 = y0 + 2 * NORMAL_TILE_HEIGHT;
-           min_x = MIN(min_x, x0);
-           min_y = MIN(min_y, y0);
-           max_x = MAX(max_x, x1);
-           max_y = MAX(max_y, y1);
-         }
-
-         /* FIXME: These overview updates should be batched as well.  Right
-          * now they account for as much as 90% of the runtime of the
-          * unqueue. */
-         overview_update_tile(ptile);
-       } unit_list_iterate_end;
-      }
-
-      if (unit_updates) {
-       tile_list_iterate(unit_updates, ptile) {
-         int x0, y0, x1, y1;
-
-         if (tile_to_canvas_pos(&x0, &y0, ptile)) {
-           y0 += NORMAL_TILE_HEIGHT - UNIT_TILE_HEIGHT;
-           x1 = x0 + UNIT_TILE_WIDTH;
-           y1 = y0 + UNIT_TILE_HEIGHT;
-           min_x = MIN(min_x, x0);
-           min_y = MIN(min_y, y0);
-           max_x = MAX(max_x, x1);
-           max_y = MAX(max_y, y1);
-         }
-
-         /* FIXME: These overview updates should be batched as well.  Right
-          * now they account for as much as 90% of the runtime of the
-          * unqueue. */
-         overview_update_tile(ptile);
-       } tile_list_iterate_end;
-      }
-
-      if (city_updates) {
-       int width = get_citydlg_canvas_width() + NORMAL_TILE_WIDTH;
-       int height = get_citydlg_canvas_height() + NORMAL_TILE_HEIGHT;
-
-       tile_list_iterate(city_updates, ptile) {
-         int x0, y0, x1, y1;
-
-         if (tile_to_canvas_pos(&x0, &y0, ptile)) {
-           x0 -= (width - NORMAL_TILE_WIDTH) / 2;
-           y0 -= (height - NORMAL_TILE_HEIGHT) / 2;
-           x1 = x0 + width;
-           y1 = y0 + height;
-           min_x = MIN(min_x, x0);
-           min_y = MIN(min_y, y0);
-           max_x = MAX(max_x, x1);
-           max_y = MAX(max_y, y1);
-         }
-
-         /* FIXME: These overview updates should be batched as well.  Right
-          * now they account for as much as 90% of the runtime of the
-          * unqueue. */
-         overview_update_tile(ptile);
-       } tile_list_iterate_end;
+      for (i = 0; i < TILE_UPDATE_COUNT; i++) {
+       if (tile_updates[i]) {
+         tile_list_iterate(tile_updates[i], ptile) {
+           int x0, y0, x1, y1;
+
+           (void) tile_to_canvas_pos(&x0, &y0, ptile);
+
+           x0 += area[i].dx;
+           y0 += area[i].dy;
+           x1 = x0 + area[i].w;
+           y1 = y0 + area[i].h;
+
+           if (x1 > 0 && x0 < mapview.width
+               && y1 > 0 && y0 < mapview.height) {
+             min_x = MIN(min_x, x0);
+             min_y = MIN(min_y, y0);
+             max_x = MAX(max_x, x1);
+             max_y = MAX(max_y, y1);
+           }
+
+           /* FIXME: These overview updates should be batched as well.
+            * Right now they account for as much as 90% of the runtime of
+            * the unqueue. */
+           overview_update_tile(ptile);
+         } tile_list_iterate_end;
+       }
       }
 
       if (min_x < max_x && min_y < max_y) {
@@ -2359,14 +2323,10 @@
       }
     }
   }
-  if (tile_updates) {
-    tile_list_unlink_all(tile_updates);
-  }
-  if (unit_updates) {
-    tile_list_unlink_all(unit_updates);
-  }
-  if (city_updates) {
-    tile_list_unlink_all(city_updates);
+  for (i = 0; i < TILE_UPDATE_COUNT; i++) {
+    if (tile_updates[i]) {
+      tile_list_unlink_all(tile_updates[i]);
+    }
   }
   needed_updates = UPDATE_NONE;
 
Index: client/mapview_common.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.h,v
retrieving revision 1.93
diff -u -r1.93 mapview_common.h
--- client/mapview_common.h     14 Feb 2005 17:52:56 -0000      1.93
+++ client/mapview_common.h     16 Feb 2005 06:23:11 -0000
@@ -203,9 +203,10 @@
   }                                                                        \
 }
 
-void refresh_tile_mapcanvas(struct tile *ptile, bool write_to_screen);
+void refresh_tile_mapcanvas(struct tile *ptile,
+                           bool full_refresh, bool write_to_screen);
 void refresh_unit_mapcanvas(struct unit *punit, struct tile *ptile,
-                           bool write_to_screen);
+                           bool full_refresh, bool write_to_screen);
 void refresh_city_mapcanvas(struct city *pcity, struct tile *ptile,
                            bool full_refresh, bool write_to_screen);
 
Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.471
diff -u -r1.471 packhand.c
--- client/packhand.c   15 Feb 2005 05:37:04 -0000      1.471
+++ client/packhand.c   16 Feb 2005 06:23:12 -0000
@@ -296,8 +296,8 @@
        punit1->hp = hp1;
 
        set_units_in_combat(NULL, NULL);
-       refresh_unit_mapcanvas(punit0, punit0->tile, FALSE);
-       refresh_unit_mapcanvas(punit1, punit1->tile, FALSE);
+       refresh_unit_mapcanvas(punit0, punit0->tile, TRUE, FALSE);
+       refresh_unit_mapcanvas(punit1, punit1->tile, TRUE, FALSE);
       }
     }
   }
@@ -586,7 +586,7 @@
 
 
   if (can_client_change_view()) {
-    refresh_tile_mapcanvas(pcity->tile, FALSE);
+    refresh_city_mapcanvas(pcity, pcity->tile, FALSE, FALSE);
   }
 
   if (city_workers_display==pcity)  {
@@ -1203,7 +1203,7 @@
   }
 
   if (repaint_unit) {
-    refresh_unit_mapcanvas(punit, punit->tile, FALSE);
+    refresh_unit_mapcanvas(punit, punit->tile, TRUE, FALSE);
   }
 
   if ((check_focus || get_unit_in_focus() == NULL) &&
@@ -1955,7 +1955,7 @@
   if (can_client_change_view()) {
     /* the tile itself (including the necessary parts of adjacent tiles) */
     if (tile_changed || old_known!=ptile->known) {
-      refresh_tile_mapcanvas(ptile, FALSE);
+      refresh_tile_mapcanvas(ptile, TRUE, FALSE);
     }
   }
 

[Prev in Thread] Current Thread [Next in Thread]