Complete.Org: Mailing Lists: Archives: freeciv-dev: May 2004:
[Freeciv-Dev] (PR#8815) double-buffer in update_map_canvas
Home

[Freeciv-Dev] (PR#8815) double-buffer in update_map_canvas

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [Freeciv-Dev] (PR#8815) double-buffer in update_map_canvas
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Sat, 22 May 2004 13:05:45 -0700
Reply-to: rt@xxxxxxxxxxx

<URL: http://rt.freeciv.org/Ticket/Display.html?id=8815 >

Currently update_map_canvas doesn't fully respect the boundaries its 
given.  That is, if you call an update on a particular rectangle 
everything within that rectangle will be fully updated, but things 
outside of the rectangle may only be partially updated.  You see this 
most clearly when moving goto lines around on the screen: when you move 
them over borders or city texts things aren't redrawn perfectly.

The solution is to use a double-buffer solution.  The drawing is first 
done to the tmp_store and then just the area of update is copied over to 
the main backing store.  This means everything within the rectangle is 
fully updated and everything outside of the rectangle is untouched. 
This makes the redraws substantially more "correct" but does take a bit 
longer (I don't have numbers on this).

This is complicated a bit by the full update situation.  If a full 
update is done (through update_map_canvas_visible or just an update that 
happens to cover the whole screen) we don't want to double-buffer.  It 
wouldn't help at all and would just make the redraw slower.  It's easy 
enough to check for this situation and avoid the double-buffer in this case.

As a side change I clip the redraw area to the area of the screen. 
gui_rect_iterate should work fine in either case but it may be slightly 
faster to avoid the extra iteration.

jason

Index: client/mapview_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.c,v
retrieving revision 1.120
diff -u -r1.120 mapview_common.c
--- client/mapview_common.c     22 May 2004 18:12:21 -0000      1.120
+++ client/mapview_common.c     22 May 2004 19:53:02 -0000
@@ -1304,13 +1304,35 @@
 **************************************************************************/
 void update_map_canvas(int canvas_x, int canvas_y, int width, int height)
 {
-  const int gui_x0 = mapview_canvas.gui_x0 + canvas_x;
-  const int gui_y0 = mapview_canvas.gui_y0 + canvas_y;
+  int gui_x0, gui_y0;
+  bool full;
+  struct canvas *tmp;
+
+  canvas_x = MAX(canvas_x, 0);
+  canvas_y = MAX(canvas_y, 0);
+  width = MIN(mapview_canvas.width - canvas_x, width);
+  height = MIN(mapview_canvas.height - canvas_y, height);
+
+  gui_x0 = mapview_canvas.gui_x0 + canvas_x;
+  gui_y0 = mapview_canvas.gui_y0 + canvas_y;
+  full = (canvas_x == 0 && canvas_y == 0
+         && width == mapview_canvas.width
+         && height == mapview_canvas.height);
 
   freelog(LOG_DEBUG,
          "update_map_canvas(pos=(%d,%d), size=(%d,%d))",
          canvas_x, canvas_y, width, height);
 
+  /* If a full redraw is done, we just draw everything onto the canvas.
+   * However if a partial redraw is done we draw everything onto the
+   * tmp_canvas then copy *just* the area of update onto the canvas. */
+  if (!full) {
+    /* Swap store and tmp_store. */
+    tmp = mapview_canvas.store;
+    mapview_canvas.store = mapview_canvas.tmp_store;
+    mapview_canvas.tmp_store = tmp;
+  }
+
   /* Clear the area.  This is necessary since some parts of the rectangle
    * may not actually have any tiles drawn on them.  This will happen when
    * the mapview is large enough so that the tile is visible in multiple
@@ -1352,6 +1374,17 @@
 
   show_city_descriptions(canvas_x, canvas_y, width, height);
 
+  if (!full) {
+    /* Swap store and tmp_store back. */
+    tmp = mapview_canvas.store;
+    mapview_canvas.store = mapview_canvas.tmp_store;
+    mapview_canvas.tmp_store = tmp;
+
+    /* And copy store to tmp_store. */
+    canvas_copy(mapview_canvas.store, mapview_canvas.tmp_store,
+               canvas_x, canvas_y, canvas_x, canvas_y, width, height);
+  }
+
   dirty_rect(canvas_x, canvas_y, width, height);
 }
 

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] (PR#8815) double-buffer in update_map_canvas, Jason Short <=