Complete.Org: Mailing Lists: Archives: freeciv-dev: February 2005:
[Freeciv-Dev] Re: (PR#12149) drawing is really slow
Home

[Freeciv-Dev] Re: (PR#12149) drawing is really slow

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] Re: (PR#12149) drawing is really slow
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Mon, 7 Feb 2005 09:33:22 -0800
Reply-to: bugs@xxxxxxxxxxx

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

Units and cities can die.  This stores a tile_list for the unit and city 
updates.  Tiles can't die so this is safer.  It also allows enqueueing 
an update for a unit right before we destroy it (for instance).

Also I forgot to mention, if the client disconnects between the queue 
and the unqueue, there is a problem.  Maybe unqueue_mapview_updates just 
needs to check if map_exists() or something before proceeding.

-jason


? fog
? fog.c
? fog.png
? foo
? data/isotrident/grid.png
? data/isotrident/grid.xcf
Index: client/mapview_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.c,v
retrieving revision 1.177
diff -u -r1.177 mapview_common.c
--- client/mapview_common.c     6 Feb 2005 23:36:20 -0000       1.177
+++ client/mapview_common.c     7 Feb 2005 17:30:53 -0000
@@ -517,6 +517,8 @@
     gui_distance_vector(&diff_x, &diff_y, start_x, start_y, gui_x0, gui_y0);
     anim_timer = renew_timer_start(anim_timer, TIMER_USER, TIMER_ACTIVE);
 
+    unqueue_mapview_updates();
+
     do {
       mytime = MIN(read_timer_seconds(anim_timer), timing_sec);
 
@@ -1268,7 +1270,7 @@
   dirty_rect(canvas_x, canvas_y, width, height);
 
   /* Make sure everything is flushed and synced before proceeding. */
-  flush_dirty();
+  unqueue_mapview_updates();
   gui_flush();
 
   myusleep(1000000);
@@ -1803,6 +1805,7 @@
 
   set_units_in_combat(punit0, punit1);
 
+  unqueue_mapview_updates();
   while (punit0->hp > hp0 || punit1->hp > hp1) {
     const int diff0 = punit0->hp - hp0, diff1 = punit1->hp - hp1;
 
@@ -1891,6 +1894,7 @@
     return;
   }
 
+  unqueue_mapview_updates();
   if (tile_visible_mapcanvas(src_tile)
       || tile_visible_mapcanvas(dest_tile)) {
     int start_x, start_y;
@@ -2077,6 +2081,9 @@
 }
 
 static enum update_type needed_updates = UPDATE_NONE;
+struct tile_list *city_updates = NULL;
+struct tile_list *unit_updates = NULL;
+struct tile_list *tile_updates = NULL;
 
 /**************************************************************************
   This function, along with unqueue_mapview_update(), helps in updating
@@ -2101,6 +2108,45 @@
 }
 
 /**************************************************************************
+  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)
+{
+  if (!tile_updates) {
+    tile_updates = tile_list_new();
+  }
+  tile_list_prepend(tile_updates, ptile);
+}
+
+/**************************************************************************
+  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)
+{
+  if (!unit_updates) {
+    unit_updates = tile_list_new();
+  }
+  tile_list_prepend(unit_updates, punit->tile);
+}
+
+/**************************************************************************
+  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)
+{
+  if (!city_updates) {
+    city_updates = tile_list_new();
+  }
+  tile_list_prepend(city_updates, pcity->tile);
+}
+
+/**************************************************************************
   See comment for queue_mapview_update().
 **************************************************************************/
 void unqueue_mapview_updates(void)
@@ -2108,10 +2154,87 @@
   freelog(LOG_DEBUG, "unqueue_mapview_update: needed_updates=%d",
          needed_updates);
 
-  if (needed_updates & UPDATE_MAP_CANVAS_VISIBLE) {
+  if ((needed_updates & UPDATE_MAP_CANVAS_VISIBLE)
+      || (needed_updates & UPDATE_CITY_DESCRIPTIONS)) {
     update_map_canvas_visible();
-  } else if (needed_updates & UPDATE_CITY_DESCRIPTIONS) {
-    update_city_descriptions();
+  } else {
+    int min_x = mapview_canvas.width, min_y = mapview_canvas.height;
+    int max_x = 0, max_y = 0;
+
+    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) {
+      tile_list_iterate(city_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;
+    }
+
+    update_map_canvas(min_x, min_y, max_x - min_x, max_y - min_y);
+  }
+  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);
   }
   needed_updates = UPDATE_NONE;
 
Index: client/mapview_common.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.h,v
retrieving revision 1.87
diff -u -r1.87 mapview_common.h
--- client/mapview_common.h     5 Feb 2005 19:26:38 -0000       1.87
+++ client/mapview_common.h     7 Feb 2005 17:30:53 -0000
@@ -288,6 +288,9 @@
                                      enum color_std *grwoth_color);
 
 void queue_mapview_update(enum update_type update);
+void queue_mapview_tile_update(struct tile *ptile);
+void queue_mapview_unit_update(struct unit *punit);
+void queue_mapview_city_update(struct city *pcity);
 void unqueue_mapview_updates(void);
 
 void map_to_overview_pos(int *overview_x, int *overview_y,
Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.464
diff -u -r1.464 packhand.c
--- client/packhand.c   7 Feb 2005 08:19:01 -0000       1.464
+++ client/packhand.c   7 Feb 2005 17:30:53 -0000
@@ -1981,14 +1981,14 @@
   if (can_client_change_view()) {
     /* the tile itself */
     if (tile_changed || old_known!=ptile->known)
-      refresh_tile_mapcanvas(ptile, FALSE);
+      queue_mapview_tile_update(ptile);
 
     /* if the terrain or the specials of the tile
        have changed it affects the adjacent tiles */
     if (tile_changed) {
       adjc_iterate(ptile, tile1) {
        if (tile_get_known(tile1) >= TILE_KNOWN_FOGGED)
-         refresh_tile_mapcanvas(tile1, FALSE);
+         queue_mapview_tile_update(tile1);
       }
       adjc_iterate_end;
       return;
@@ -1999,7 +1999,7 @@
     if (old_known == TILE_UNKNOWN && packet->known >= TILE_KNOWN_FOGGED) {     
       cardinal_adjc_iterate(ptile, tile1) {
        if (tile_get_known(tile1) >= TILE_KNOWN_FOGGED)
-         refresh_tile_mapcanvas(tile1, FALSE);
+         queue_mapview_tile_update(tile1);
       } cardinal_adjc_iterate_end;
     }
   }
Index: common/map.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/map.h,v
retrieving revision 1.233
diff -u -r1.233 map.h
--- common/map.h        22 Jan 2005 19:45:43 -0000      1.233
+++ common/map.h        7 Feb 2005 17:30:54 -0000
@@ -55,6 +55,14 @@
   char *spec_sprite;
 };
 
+/* get 'struct tile_list' and related functions: */
+#define SPECLIST_TAG tile
+#define SPECLIST_TYPE struct tile
+#include "speclist.h"
+
+#define tile_list_iterate(tile_list, ptile) \
+    TYPED_LIST_ITERATE(struct tile, tile_list, ptile)
+#define tile_list_iterate_end  LIST_ITERATE_END
 
 /****************************************************************
 miscellaneous terrain information

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