Complete.Org: Mailing Lists: Archives: freeciv-dev: February 2003:
[Freeciv-Dev] Re: (PR#3424) New flush code
Home

[Freeciv-Dev] Re: (PR#3424) New flush code

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: bursig@xxxxxxxxx
Subject: [Freeciv-Dev] Re: (PR#3424) New flush code
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Thu, 27 Feb 2003 13:12:43 -0800
Reply-to: rt@xxxxxxxxxxxxxx

Jason Short wrote:
> Raimar Falke wrote:

> It seems reasonable to take this a step further and do it the same way 
> for gui-sdl.  I believe this can be done with SDL_AddTimer, but I'm not 
> familiar enough with the code to write this.  If that were done then all 
> GUIs (except MUI which just has stubs) would be supported, and we could 
> remove all flush_dirty calls from the common code except for the 
> animation ones.
New patch attached.  This has now been tested under gui-sdl and 
gui-win32 as well.

jason


Index: client/climisc.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/climisc.c,v
retrieving revision 1.112
diff -u -r1.112 climisc.c
--- client/climisc.c    2003/02/15 20:26:17     1.112
+++ client/climisc.c    2003/02/27 21:04:38
@@ -111,7 +111,7 @@
            get_nation_name(city_owner(pcity)->nation), pcity->x, pcity->y);
   }
 
-  refresh_tile_mapcanvas(x, y, TRUE);
+  refresh_tile_mapcanvas(x, y, FALSE);
 }
 
 /**************************************************************************
@@ -142,7 +142,7 @@
   popdown_city_dialog(pcity);
   game_remove_city(pcity);
   city_report_dialog_update();
-  refresh_tile_mapcanvas(x, y, TRUE);
+  refresh_tile_mapcanvas(x, y, FALSE);
 }
 
 /**************************************************************************
Index: client/control.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/control.c,v
retrieving revision 1.95
diff -u -r1.95 control.c
--- client/control.c    2003/02/20 21:58:14     1.95
+++ client/control.c    2003/02/27 21:04:39
@@ -110,7 +110,7 @@
     auto_center_on_focus_unit();
 
     punit->focus_status=FOCUS_AVAIL;
-    refresh_tile_mapcanvas(punit->x, punit->y, TRUE);
+    refresh_tile_mapcanvas(punit->x, punit->y, FALSE);
 
     if (punit->activity != ACTIVITY_IDLE || punit->ai.control)  {
       punit->activity = ACTIVITY_IDLE;
@@ -124,7 +124,7 @@
   if (punit_old_focus
       && (!punit || !same_pos(punit_old_focus->x, punit_old_focus->y,
                                   punit->x, punit->y))) {
-    refresh_tile_mapcanvas(punit_old_focus->x, punit_old_focus->y, TRUE);
+    refresh_tile_mapcanvas(punit_old_focus->x, punit_old_focus->y, FALSE);
   }
 
   update_unit_info_label(punit);
@@ -215,7 +215,7 @@
    * because above we change punit_focus directly.
    */
   if(punit_old_focus && punit_old_focus!=punit_focus)
-    refresh_tile_mapcanvas(punit_old_focus->x, punit_old_focus->y, TRUE);
+    refresh_tile_mapcanvas(punit_old_focus->x, punit_old_focus->y, FALSE);
 
   set_unit_focus(punit_focus);
 
@@ -1170,7 +1170,7 @@
   unit_list_unlink(&map_get_tile(x, y)->units, punit);
 
   if(!pinfo->carried)
-    refresh_tile_mapcanvas(x, y, was_teleported);
+    refresh_tile_mapcanvas(x, y, FALSE);
   
   if(game.player_idx==punit->owner && punit->activity!=ACTIVITY_GOTO && 
      auto_center_on_unit && punit->activity!=ACTIVITY_SENTRY &&
@@ -1184,7 +1184,7 @@
       dx=1;
     if(smooth_move_units)
       move_unit_map_canvas(punit, x, y, dx, pinfo->y - punit->y);
-    refresh_tile_mapcanvas(x, y, TRUE);
+    refresh_tile_mapcanvas(x, y, FALSE);
   }
     
   punit->x=pinfo->x;
@@ -1203,12 +1203,12 @@
     } unit_list_iterate_end;
   out:
     if (refresh) {
-      refresh_tile_mapcanvas(x, y, TRUE);
+      refresh_tile_mapcanvas(x, y, FALSE);
     }
   } square_iterate_end;
   
   if(!pinfo->carried && tile_get_known(punit->x,punit->y) == TILE_KNOWN)
-    refresh_tile_mapcanvas(punit->x, punit->y, TRUE);
+    refresh_tile_mapcanvas(punit->x, punit->y, FALSE);
 
   if(get_unit_in_focus()==punit) update_menus();
 }
Index: client/mapview_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.c,v
retrieving revision 1.33
diff -u -r1.33 mapview_common.c
--- client/mapview_common.c     2003/02/27 00:31:09     1.33
+++ client/mapview_common.c     2003/02/27 21:04:40
@@ -45,7 +45,7 @@
   if (tile_visible_mapcanvas(x, y)) {
     update_map_canvas(x, y, 1, 1, FALSE);
 
-    if (write_to_screen && (draw_city_names || draw_city_productions)) {
+    if (draw_city_names || draw_city_productions) {
       /* FIXME: update_map_canvas() will overwrite the city descriptions.
        * This is a workaround that redraws the city descriptions (most of
        * the time).  Although it seems inefficient to redraw the
@@ -91,12 +91,7 @@
     }
 
     if (write_to_screen) {
-      int canvas_start_x, canvas_start_y;
-
-      get_canvas_xy(x, y, &canvas_start_x, &canvas_start_y);
-      canvas_start_y += NORMAL_TILE_HEIGHT - UNIT_TILE_HEIGHT;
-      flush_mapcanvas(canvas_start_x, canvas_start_y,
-                     UNIT_TILE_WIDTH, UNIT_TILE_HEIGHT);
+      flush_dirty();
     }
   }
   overview_update_tile(x, y);
@@ -628,6 +623,8 @@
 void update_map_canvas(int x, int y, int width, int height, 
                       bool write_to_screen)
 {
+  int canvas_start_x, canvas_start_y;
+
   freelog(LOG_DEBUG,
          "update_map_canvas(pos=(%d,%d), size=(%d,%d), write_to_screen=%d)",
          x, y, width, height, write_to_screen);
@@ -702,31 +699,25 @@
 
 
     /* Lastly draw our changes to the screen. */
-    if (write_to_screen) {
-      int canvas_start_x, canvas_start_y;
+    /* top left corner */
+    get_canvas_xy(x, y, &canvas_start_x, &canvas_start_y);
 
-      /* top left corner */
-      get_canvas_xy(x, y, &canvas_start_x, &canvas_start_y);
+    /* top left corner in isometric view */
+    canvas_start_x -= height * NORMAL_TILE_WIDTH / 2;
 
-      /* top left corner in isometric view */
-      canvas_start_x -= height * NORMAL_TILE_WIDTH / 2;
+    /* because of where get_canvas_xy() sets canvas_x */
+    canvas_start_x += NORMAL_TILE_WIDTH / 2;
 
-      /* because of where get_canvas_xy() sets canvas_x */
-      canvas_start_x += NORMAL_TILE_WIDTH / 2;
-
-      /* And because units fill a little extra */
-      canvas_start_y -= NORMAL_TILE_HEIGHT / 2;
-
-      /* Here we draw a rectangle that includes the updated tiles.  This
-       * method can fail if the area wraps off one side of the screen and
-       * back to the other (although this will not be a problem for
-       * update_map_canvas_visible(). */
-      flush_mapcanvas(canvas_start_x, canvas_start_y,
-                     (height + width) * NORMAL_TILE_WIDTH / 2,
-                     (height + width) * NORMAL_TILE_HEIGHT / 2
-                     + NORMAL_TILE_HEIGHT / 2);
-    }
-
+    /* And because units fill a little extra */
+    canvas_start_y += NORMAL_TILE_HEIGHT - UNIT_TILE_HEIGHT;
+
+    /* Here we draw a rectangle that includes the updated tiles.  This
+     * method can fail if the area wraps off one side of the screen and
+     * back to the other. */
+    dirty_rect(canvas_start_x, canvas_start_y,
+              (height + width) * NORMAL_TILE_WIDTH / 2,
+              (height + width) * NORMAL_TILE_HEIGHT / 2
+              + NORMAL_TILE_HEIGHT / 2);
   } else {
     /* not isometric */
     int map_x, map_y;
@@ -741,18 +732,20 @@
       }
     }
 
-    if (write_to_screen) {
-      int canvas_x, canvas_y;
+    /* Here we draw a rectangle that includes the updated tiles.  This
+     * method can fail if the area wraps off one side of the screen and
+     * back to the other. */
+    get_canvas_xy(x, y, &canvas_start_x, &canvas_start_y);
+    dirty_rect(canvas_start_x, canvas_start_y,
+              width * NORMAL_TILE_WIDTH,
+              height * NORMAL_TILE_HEIGHT);
+  }
 
-      /* Here we draw a rectangle that includes the updated tiles.  This
-       * method can fail if the area wraps off one side of the screen and
-       * back to the other (although this will not be a problem for
-       * update_map_canvas_visible(). */
-      get_canvas_xy(x, y, &canvas_x, &canvas_y);
-      flush_mapcanvas(canvas_x, canvas_y,
-                     width * NORMAL_TILE_WIDTH,
-                     height * NORMAL_TILE_HEIGHT);
-    }
+  if (write_to_screen) {
+    /* We never want a partial flush; that would leave the screen in an
+     * inconsistent state.  If the caller tells us to write_to_screen we
+     * simply flush everything immediately. */
+    flush_dirty();
   }
 }
 
@@ -769,6 +762,8 @@
   map_tile_width = (map_win_width - 1) / NORMAL_TILE_WIDTH + 1;
   map_tile_height = (map_win_height - 1) / NORMAL_TILE_HEIGHT + 1;
 
+  dirty_all();
+
   if (is_isometric) {
     /* just find a big rectangle that includes the whole visible area. The
        invisible tiles will not be drawn. */
@@ -783,8 +778,6 @@
   }
 
   show_city_descriptions();
-
-  flush_mapcanvas(0, 0, map_win_width, map_win_height);
 }
 
 /**************************************************************************
@@ -864,10 +857,10 @@
     update_map_canvas(MIN(src_x, dest_x), MIN(src_y, dest_y),
                      src_x == dest_x ? 1 : 2,
                      src_y == dest_y ? 1 : 2,
-                     TRUE);
+                     FALSE);
   } else {
-    refresh_tile_mapcanvas(src_x, src_y, TRUE);
-    refresh_tile_mapcanvas(dest_x, dest_y, TRUE);
+    refresh_tile_mapcanvas(src_x, src_y, FALSE);
+    refresh_tile_mapcanvas(dest_x, dest_y, FALSE);
 
     if (NORMAL_TILE_WIDTH % 2 == 0 || NORMAL_TILE_HEIGHT % 2 == 0) {
       if (dir == DIR8_NORTHEAST) {
@@ -876,12 +869,12 @@
        if (!MAPSTEP(dest_x, dest_y, src_x, src_y, DIR8_EAST)) {
          assert(0);
        }
-       refresh_tile_mapcanvas(dest_x, dest_y, TRUE);
+       refresh_tile_mapcanvas(dest_x, dest_y, FALSE);
       } else if (dir == DIR8_SOUTHWEST) {      /* the same */
        if (!MAPSTEP(dest_x, dest_y, src_x, src_y, DIR8_SOUTH)) {
          assert(0);
        }
-       refresh_tile_mapcanvas(dest_x, dest_y, TRUE);
+       refresh_tile_mapcanvas(dest_x, dest_y, FALSE);
       }
     }
   }
@@ -913,6 +906,8 @@
     assert(0);
   }
 
+  flush_dirty();
+
   if (player_can_see_unit(game.player_ptr, punit) &&
       (tile_visible_mapcanvas(map_x, map_y) ||
        tile_visible_mapcanvas(dest_x, dest_y))) {
@@ -1117,6 +1112,8 @@
     update_city_descriptions();
   }
   needed_updates = UPDATE_NONE;
+
+  flush_dirty();
 }
 
 /**************************************************************************
Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.293
diff -u -r1.293 packhand.c
--- client/packhand.c   2003/02/20 23:00:55     1.293
+++ client/packhand.c   2003/02/27 21:04:41
@@ -190,6 +190,7 @@
 **************************************************************************/
 void handle_nuke_tile(struct packet_nuke_tile *packet)
 {
+  flush_dirty();
   put_nuke_mushroom_pixmaps(packet->x, packet->y);
 }
 
@@ -223,14 +224,15 @@
                       unit_type(punit1)->sound_fight_alt);
 
       if (do_combat_animation) {
+       flush_dirty();
        decrease_unit_hp_smooth(punit0, hp0, punit1, hp1);
       } else {
        punit0->hp = hp0;
        punit1->hp = hp1;
 
        set_units_in_combat(NULL, NULL);
-       refresh_tile_mapcanvas(punit0->x, punit0->y, TRUE);
-       refresh_tile_mapcanvas(punit1->x, punit1->y, TRUE);
+       refresh_tile_mapcanvas(punit0->x, punit0->y, FALSE);
+       refresh_tile_mapcanvas(punit1->x, punit1->y, FALSE);
       }
     }
   }
@@ -503,7 +505,7 @@
                      CITY_MAP_SIZE, CITY_MAP_SIZE, FALSE);
     queue_mapview_update(UPDATE_CITY_DESCRIPTIONS);
   } else {
-    refresh_tile_mapcanvas(pcity->x, pcity->y, TRUE);
+    refresh_tile_mapcanvas(pcity->x, pcity->y, FALSE);
   }
 
   if (city_workers_display==pcity)  {
@@ -914,7 +916,7 @@
 
       if(punit->owner==game.player_idx) 
         refresh_unit_city_dialogs(punit);
-      /*      refresh_tile_mapcanvas(punit->x, punit->y, TRUE);
+      /*      refresh_tile_mapcanvas(punit->x, punit->y, FALSE);
        *      update_unit_pix_label(punit);
        *      update_unit_focus();
        */
@@ -982,7 +984,7 @@
       else {
        do_move_unit(punit, packet); /* nice to see where a unit is going */
        client_remove_unit(punit);
-       refresh_tile_mapcanvas(packet->x, packet->y, TRUE);
+       refresh_tile_mapcanvas(packet->x, packet->y, FALSE);
         return;
       }
       if(pcity)  {
@@ -1052,7 +1054,7 @@
     /*fog of war*/
     if (!(tile_get_known(punit->x,punit->y) == TILE_KNOWN)) {
       client_remove_unit(punit);
-      refresh_tile_mapcanvas(dest_x, dest_y, TRUE);
+      refresh_tile_mapcanvas(dest_x, dest_y, FALSE);
     }
     agents_unit_changed(punit);
   }
@@ -1093,7 +1095,7 @@
   }
 
   if(repaint_unit)
-    refresh_tile_mapcanvas(punit->x, punit->y, TRUE);
+    refresh_tile_mapcanvas(punit->x, punit->y, FALSE);
 
   if (check_focus || get_unit_in_focus() == NULL)
     update_unit_focus(); 
@@ -1703,14 +1705,14 @@
 
     /* the tile itself */
     if (tile_changed || old_known!=ptile->known)
-      refresh_tile_mapcanvas(x, y, TRUE);
+      refresh_tile_mapcanvas(x, y, FALSE);
 
     /* if the terrain or the specials of the tile
        have changed it affects the adjacent tiles */
     if (tile_changed) {
       adjc_iterate(x, y, x1, y1) {
        if (tile_get_known(x1, y1) >= TILE_KNOWN_FOGGED)
-         refresh_tile_mapcanvas(x1, y1, TRUE);
+         refresh_tile_mapcanvas(x1, y1, FALSE);
       }
       adjc_iterate_end;
       return;
@@ -1721,7 +1723,7 @@
     if (old_known == TILE_UNKNOWN && packet->known >= TILE_KNOWN_FOGGED) {     
       cartesian_adjacent_iterate(x, y, x1, y1) {
        if (tile_get_known(x1, y1) >= TILE_KNOWN_FOGGED)
-         refresh_tile_mapcanvas(x1, y1, TRUE);
+         refresh_tile_mapcanvas(x1, y1, FALSE);
       }
       cartesian_adjacent_iterate_end;
     }
Index: client/gui-gtk/mapview.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk/mapview.c,v
retrieving revision 1.161
diff -u -r1.161 mapview.c
--- client/gui-gtk/mapview.c    2003/02/27 00:31:10     1.161
+++ client/gui-gtk/mapview.c    2003/02/27 21:04:42
@@ -790,6 +790,83 @@
   gdk_draw_pixmap(map_canvas->window, civ_gc, map_canvas_store,
                  canvas_x, canvas_y, canvas_x, canvas_y,
                  pixel_width, pixel_height);
+
+}
+
+#define MAX_DIRTY_RECTS 20
+static int num_dirty_rects = 0;
+static GdkRectangle dirty_rects[MAX_DIRTY_RECTS];
+static bool is_flush_queued = FALSE;
+
+/**************************************************************************
+  A callback invoked as a result of gtk_idle_add, this function simply
+  flushes the mapview canvas.
+**************************************************************************/
+static gint unqueue_flush(gpointer data)
+{
+  flush_dirty();
+  is_flush_queued = FALSE;
+  return 0;
+}
+
+/**************************************************************************
+  Called when a region is marked dirty, this function queues a flush event
+  to be handled later by GTK.  The flush may end up being done
+  by freeciv before then, in which case it will be a wasted call.
+**************************************************************************/
+static void queue_flush(void)
+{
+  if (!is_flush_queued) {
+    gtk_idle_add(unqueue_flush, NULL);
+    is_flush_queued = TRUE;
+  }
+}
+
+/**************************************************************************
+  Mark the rectangular region as 'dirty' so that we know to flush it
+  later.
+**************************************************************************/
+void dirty_rect(int canvas_x, int canvas_y,
+               int pixel_width, int pixel_height)
+{
+  if (num_dirty_rects < MAX_DIRTY_RECTS) {
+    dirty_rects[num_dirty_rects].x = canvas_x;
+    dirty_rects[num_dirty_rects].y = canvas_y;
+    dirty_rects[num_dirty_rects].width = pixel_width;
+    dirty_rects[num_dirty_rects].height = pixel_height;
+    num_dirty_rects++;
+    queue_flush();
+  }
+}
+
+/**************************************************************************
+  Mark the entire screen area as "dirty" so that we can flush it later.
+**************************************************************************/
+void dirty_all(void)
+{
+  num_dirty_rects = MAX_DIRTY_RECTS;
+  queue_flush();
+}
+
+/**************************************************************************
+  Flush all regions that have been previously marked as dirty.  See
+  dirty_rect and dirty_all.  This function is generally called after we've
+  processed a batch of drawing operations.
+**************************************************************************/
+void flush_dirty(void)
+{
+  if (num_dirty_rects == MAX_DIRTY_RECTS) {
+    flush_mapcanvas(0, 0, map_canvas->allocation.width,
+                   map_canvas->allocation.height);
+  } else {
+    int i;
+
+    for (i = 0; i < num_dirty_rects; i++) {
+      flush_mapcanvas(dirty_rects[i].x, dirty_rects[i].y,
+                     dirty_rects[i].width, dirty_rects[i].height);
+    }
+  }
+  num_dirty_rects = 0;
 }
 
 /**************************************************************************
Index: client/gui-gtk-2.0/mapview.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/mapview.c,v
retrieving revision 1.49
diff -u -r1.49 mapview.c
--- client/gui-gtk-2.0/mapview.c        2003/02/27 00:31:10     1.49
+++ client/gui-gtk-2.0/mapview.c        2003/02/27 21:04:43
@@ -827,6 +827,45 @@
 }
 
 /**************************************************************************
+  Mark the rectangular region as "dirty" so that we know to flush it
+  later.
+**************************************************************************/
+void dirty_rect(int canvas_x, int canvas_y,
+               int pixel_width, int pixel_height)
+{
+  /* GDK gives an error if we invalidate out-of-bounds parts of the
+     window. */
+  GdkRectangle rect = {MAX(canvas_x, 0), MAX(canvas_y, 0),
+                      MIN(pixel_width,
+                          map_canvas->allocation.width - canvas_x),
+                      MIN(pixel_height,
+                          map_canvas->allocation.height - canvas_y)};
+
+  gdk_window_invalidate_rect(map_canvas->window, &rect, FALSE);
+}
+
+/**************************************************************************
+  Mark the entire screen area as "dirty" so that we can flush it later.
+**************************************************************************/
+void dirty_all(void)
+{
+  GdkRectangle rect = {0, 0, map_canvas->allocation.width,
+                      map_canvas->allocation.height};
+
+  gdk_window_invalidate_rect(map_canvas->window, &rect, FALSE);
+}
+
+/**************************************************************************
+  Flush all regions that have been previously marked as dirty.  See
+  dirty_rect and dirty_all.  This function is generally called after we've
+  processed a batch of drawing operations.
+**************************************************************************/
+void flush_dirty(void)
+{
+  gdk_window_process_updates(map_canvas->window, FALSE);
+}
+
+/**************************************************************************
  Update display of descriptions associated with cities on the main map.
 **************************************************************************/
 void update_city_descriptions(void)
Index: client/gui-mui/mapview.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-mui/mapview.c,v
retrieving revision 1.58
diff -u -r1.58 mapview.c
--- client/gui-mui/mapview.c    2003/02/04 23:12:31     1.58
+++ client/gui-mui/mapview.c    2003/02/27 21:04:44
@@ -462,6 +462,34 @@
 }
 
 /**************************************************************************
+  Mark the rectangular region as 'dirty' so that we know to flush it
+  later.
+**************************************************************************/
+void dirty_rect(int canvas_x, int canvas_y,
+               int pixel_width, int pixel_height)
+{
+  /* PORTME */
+}
+
+/**************************************************************************
+  Mark the entire screen area as "dirty" so that we can flush it later.
+**************************************************************************/
+void dirty_all(void)
+{
+  /* PORTME */
+}
+
+/**************************************************************************
+  Flush all regions that have been previously marked as dirty.  See
+  dirty_rect and dirty_all.  This function is generally called after we've
+  processed a batch of drawing operations.
+**************************************************************************/
+void flush_dirty(void)
+{
+  /* PORTME */
+}
+
+/**************************************************************************
  Update display of descriptions associated with cities on the main map.
 **************************************************************************/
 void update_city_descriptions(void)
Index: client/gui-sdl/gui_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-sdl/gui_main.c,v
retrieving revision 1.18
diff -u -r1.18 gui_main.c
--- client/gui-sdl/gui_main.c   2003/02/27 20:05:25     1.18
+++ client/gui-sdl/gui_main.c   2003/02/27 21:04:44
@@ -107,7 +107,8 @@
   NET = 1,
   ANIM = 2,
   TRY_AUTO_CONNECT = 3,
-  SHOW_WIDGET_INFO_LABBEL = 4
+  SHOW_WIDGET_INFO_LABBEL = 4,
+  FLUSH = 5
 };
 
 Uint32 SDL_Client_Flags = 0;
@@ -125,6 +126,7 @@
 static SDL_Event *pNet_User_Event = NULL;
 static SDL_Event *pAnim_User_Event = NULL;
 static SDL_Event *pInfo_User_Event = NULL;
+SDL_Event flush_user_event;
 
 Uint32 widget_info_cunter = 0;
 
@@ -372,6 +374,9 @@
          }
          widget_info_cunter = 1;
        break;
+      case FLUSH:
+       unqueue_flush();
+       break;
        default:
        break;
       }    
@@ -661,6 +666,10 @@
   __Info_User_Event.user.data1 = NULL;
   __Info_User_Event.user.data2 = NULL;
   pInfo_User_Event = &__Info_User_Event;
+
+  flush_user_event.type = SDL_USEREVENT;
+  flush_user_event.user.code = FLUSH;
+  flush_user_event.user.data1 = flush_user_event.user.data2 = NULL;
   
   smooth_move_unit_steps = 8;
   
Index: client/gui-sdl/gui_main.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-sdl/gui_main.h,v
retrieving revision 1.9
diff -u -r1.9 gui_main.h
--- client/gui-sdl/gui_main.h   2003/02/21 03:40:06     1.9
+++ client/gui-sdl/gui_main.h   2003/02/27 21:04:44
@@ -53,4 +53,6 @@
 
 void add_autoconnect_to_timer(void);
 
+extern SDL_Event flush_user_event;
+
 #endif                         /* FC__GUI_MAIN_H */
Index: client/gui-sdl/mapview.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-sdl/mapview.c,v
retrieving revision 1.32
diff -u -r1.32 mapview.c
--- client/gui-sdl/mapview.c    2003/02/27 20:05:25     1.32
+++ client/gui-sdl/mapview.c    2003/02/27 21:04:46
@@ -240,6 +240,31 @@
   }
 }
 
+static bool is_flush_queued = FALSE;
+
+/**************************************************************************
+  A callback invoked as a result of gtk_idle_add, this function simply
+  flushes the mapview canvas.
+**************************************************************************/
+void unqueue_flush(void)
+{
+  flush_dirty();
+  is_flush_queued = FALSE;
+}
+
+/**************************************************************************
+  Called when a region is marked dirty, this function queues a flush event
+  to be handled later by GTK.  The flush may end up being done
+  by freeciv before then, in which case it will be a wasted call.
+**************************************************************************/
+static void queue_flush(void)
+{
+  if (!is_flush_queued) {
+    SDL_PushEvent(&flush_user_event);
+    is_flush_queued = TRUE;
+  }
+}
+
 /**************************************************************************
   Save Flush area used by "end" flush.
 **************************************************************************/
@@ -249,6 +274,7 @@
   SDL_Rect Rect = {canvas_x, canvas_y, pixel_width, pixel_height};
   if ((Main.rects_count < RECT_LIMIT) && correct_rect_region(&Rect)) {
     Main.rects[Main.rects_count++] = Rect;
+    queue_flush();
   }
 }
 
@@ -259,6 +285,7 @@
 {
   if ((Main.rects_count < RECT_LIMIT) && correct_rect_region(&Rect)) {
     Main.rects[Main.rects_count++] = Rect;
+    queue_flush();
   }
 }
 
@@ -268,6 +295,7 @@
 void dirty_all(void)
 {
   Main.rects_count = RECT_LIMIT;
+  queue_flush();
 }
 
 /**************************************************************************
Index: client/gui-sdl/mapview.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-sdl/mapview.h,v
retrieving revision 1.5
diff -u -r1.5 mapview.h
--- client/gui-sdl/mapview.h    2003/02/21 03:40:06     1.5
+++ client/gui-sdl/mapview.h    2003/02/27 21:04:46
@@ -38,6 +38,7 @@
 void put_unit_pixmap_draw(struct unit *pUnit, SDL_Surface * pDest,
                          Sint16 map_x, Sint16 map_y);
 void flush_rect(SDL_Rect rect);
+void unqueue_flush(void);
 void sdl_dirty_rect(SDL_Rect rect);
 
 #endif /* FC__MAPVIEW_H */
Index: client/gui-stub/mapview.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-stub/mapview.c,v
retrieving revision 1.29
diff -u -r1.29 mapview.c
--- client/gui-stub/mapview.c   2003/02/27 00:31:10     1.29
+++ client/gui-stub/mapview.c   2003/02/27 21:04:46
@@ -245,6 +245,33 @@
   /* PORTME */
 }
 
+/**************************************************************************
+  Mark the rectangular region as 'dirty' so that we know to flush it
+  later.
+**************************************************************************/
+void dirty_rect(int canvas_x, int canvas_y,
+               int pixel_width, int pixel_height)
+{
+  /* PORTME */
+}
+
+/**************************************************************************
+  Mark the entire screen area as "dirty" so that we can flush it later.
+**************************************************************************/
+void dirty_all(void)
+{
+  /* PORTME */
+}
+
+/**************************************************************************
+  Flush all regions that have been previously marked as dirty.  See
+  dirty_rect and dirty_all.  This function is generally called after we've
+  processed a batch of drawing operations.
+**************************************************************************/
+void flush_dirty(void)
+{
+  /* PORTME */
+}
 
 /**************************************************************************
   Update (refresh) the locations of the mapview scrollbars (if it uses
Index: client/gui-win32/mapview.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-win32/mapview.c,v
retrieving revision 1.61
diff -u -r1.61 mapview.c
--- client/gui-win32/mapview.c  2003/02/27 00:31:10     1.61
+++ client/gui-win32/mapview.c  2003/02/27 21:04:47
@@ -537,6 +537,83 @@
   DeleteDC(mapstoredc);
 }
 
+#define MAX_DIRTY_RECTS 20
+static int num_dirty_rects = 0;
+static struct {
+  int x, y, w, h;
+} dirty_rects[MAX_DIRTY_RECTS];
+bool is_flush_queued = FALSE;
+
+/**************************************************************************
+  A callback invoked as a result of a timer event, this function simply
+  flushes the mapview canvas.
+**************************************************************************/
+static VOID CALLBACK unqueue_flush(HWND hwnd, UINT uMsg, UINT idEvent,
+                                  DWORD dwTime)
+{
+  flush_dirty();
+  is_flush_queued = FALSE;
+}
+
+/**************************************************************************
+  Called when a region is marked dirty, this function queues a flush event
+  to be handled later.  The flush may end up being done by freeciv before
+  then, in which case it will be a wasted call.
+**************************************************************************/
+static void queue_flush(void)
+{
+  if (!is_flush_queued) {
+    SetTimer(root_window, 4, 0, unqueue_flush);
+    is_flush_queued = TRUE;
+  }
+}
+
+/**************************************************************************
+  Mark the rectangular region as 'dirty' so that we know to flush it
+  later.
+**************************************************************************/
+void dirty_rect(int canvas_x, int canvas_y,
+               int pixel_width, int pixel_height)
+{
+  if (num_dirty_rects < MAX_DIRTY_RECTS) {
+    dirty_rects[num_dirty_rects].x = canvas_x;
+    dirty_rects[num_dirty_rects].y = canvas_y;
+    dirty_rects[num_dirty_rects].w = pixel_width;
+    dirty_rects[num_dirty_rects].h = pixel_height;
+    num_dirty_rects++;
+    queue_flush();
+  }
+}
+
+/**************************************************************************
+  Mark the entire screen area as "dirty" so that we can flush it later.
+**************************************************************************/
+void dirty_all(void)
+{
+  num_dirty_rects = MAX_DIRTY_RECTS;
+  queue_flush();
+}
+
+/**************************************************************************
+  Flush all regions that have been previously marked as dirty.  See
+  dirty_rect and dirty_all.  This function is generally called after we've
+  processed a batch of drawing operations.
+**************************************************************************/
+void flush_dirty(void)
+{
+  if (num_dirty_rects == MAX_DIRTY_RECTS) {
+    flush_mapcanvas(0, 0, map_win_width, map_win_height);
+  } else {
+    int i;
+
+    for (i = 0; i < num_dirty_rects; i++) {
+      flush_mapcanvas(dirty_rects[i].x, dirty_rects[i].y,
+                     dirty_rects[i].w, dirty_rects[i].h);
+    }
+  }
+  num_dirty_rects = 0;
+}
+
 /**************************************************************************
 
 **************************************************************************/
Index: client/gui-xaw/mapview.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-xaw/mapview.c,v
retrieving revision 1.128
diff -u -r1.128 mapview.c
--- client/gui-xaw/mapview.c    2003/02/27 00:31:11     1.128
+++ client/gui-xaw/mapview.c    2003/02/27 21:04:48
@@ -701,6 +701,83 @@
            canvas_x, canvas_y);
 }
 
+#define MAX_DIRTY_RECTS 20
+static int num_dirty_rects = 0;
+static XRectangle dirty_rects[MAX_DIRTY_RECTS];
+bool is_flush_queued = FALSE;
+
+/**************************************************************************
+  A callback invoked as a result of a 0-length timer, this function simply
+  flushes the mapview canvas.
+**************************************************************************/
+static void unqueue_flush(XtPointer client_data, XtIntervalId * id)
+{
+  flush_dirty();
+  is_flush_queued = FALSE;
+}
+
+/**************************************************************************
+  Called when a region is marked dirty, this function queues a flush event
+  to be handled later by Xaw.  The flush may end up being done
+  by freeciv before then, in which case it will be a wasted call.
+**************************************************************************/
+static void queue_flush(void)
+{
+  if (!is_flush_queued) {
+    (void) XtAppAddTimeOut(app_context, 0, unqueue_flush, NULL);
+    is_flush_queued = TRUE;
+  }
+}
+
+/**************************************************************************
+  Mark the rectangular region as 'dirty' so that we know to flush it
+  later.
+**************************************************************************/
+void dirty_rect(int canvas_x, int canvas_y,
+               int pixel_width, int pixel_height)
+{
+  if (num_dirty_rects < MAX_DIRTY_RECTS) {
+    dirty_rects[num_dirty_rects].x = canvas_x;
+    dirty_rects[num_dirty_rects].y = canvas_y;
+    dirty_rects[num_dirty_rects].width = pixel_width;
+    dirty_rects[num_dirty_rects].height = pixel_height;
+    num_dirty_rects++;
+    queue_flush();
+  }
+}
+
+/**************************************************************************
+  Mark the entire screen area as "dirty" so that we can flush it later.
+**************************************************************************/
+void dirty_all(void)
+{
+  num_dirty_rects = MAX_DIRTY_RECTS;
+  queue_flush();
+}
+
+/**************************************************************************
+  Flush all regions that have been previously marked as dirty.  See
+  dirty_rect and dirty_all.  This function is generally called after we've
+  processed a batch of drawing operations.
+**************************************************************************/
+void flush_dirty(void)
+{
+  if (num_dirty_rects == MAX_DIRTY_RECTS) {
+    Dimension width, height;
+
+    XtVaGetValues(map_canvas, XtNwidth, &width, XtNheight, &height, NULL);
+    flush_mapcanvas(0, 0, width, height);
+  } else {
+    int i;
+
+    for (i = 0; i < num_dirty_rects; i++) {
+      flush_mapcanvas(dirty_rects[i].x, dirty_rects[i].y,
+                     dirty_rects[i].width, dirty_rects[i].height);
+    }
+  }
+  num_dirty_rects = 0;
+}
+
 /**************************************************************************
 ...
 **************************************************************************/
Index: client/include/mapview_g.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/include/mapview_g.h,v
retrieving revision 1.34
diff -u -r1.34 mapview_g.h
--- client/include/mapview_g.h  2003/02/27 00:31:11     1.34
+++ client/include/mapview_g.h  2003/02/27 21:04:49
@@ -59,6 +59,10 @@
                  int start_x, int start_y, int dx, int dy);
 void flush_mapcanvas(int canvas_x, int canvas_y,
                     int pixel_width, int pixel_height);
+void dirty_rect(int canvas_x, int canvas_y,
+               int pixel_width, int pixel_height);
+void dirty_all(void);
+void flush_dirty(void);
 
 void update_map_canvas_scrollbars(void);
 

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