[Freeciv-Dev] Re: (PR#3424) New flush code
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Raimar Falke wrote:
> On Tue, Mar 04, 2003 at 07:26:30PM -0800, Jason Short wrote:
>
>>Raimar Falke wrote:
>>
>>>On Sun, Mar 02, 2003 at 11:49:05PM -0800, Jason Short wrote:
>>
>>>>+static void queue_flush(void)
>>>>+{
>>>>+ if (!is_flush_queued) {
>>>>+ if (SDL_PushEvent(&flush_user_event) == 0) {
>>>>+ is_flush_queued = TRUE;
>>>>+ }
>>>
>>>
>>>>+ /* Else nothing... */
>>>
>>>
>>>Here have lost a flush call. Bad.
>>
>>This should be sufficiently rare that it's not *that* bad. I don't
>>really see a way around it.
>
>
> We can at least write "You stomped about an SDL limitation please
> report to freeciv-dev@..." This way we can get an grip how common this
> is.
Done. I've also updated it to some other CVS changes.
> What about a new doc/README.mapview? It will talk about the layers,
> where animation, grid and goto lines are drawn, what buffers exists
> and so on. I think that you have already written this. You can recycle
> one of your mails for this.
I will (hopefully) provide a doc/README.drawing as a separate patch.
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/03/06 11:12:07
@@ -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/03/06 11:12:08
@@ -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.36
diff -u -r1.36 mapview_common.c
--- client/mapview_common.c 2003/03/06 09:35:11 1.36
+++ client/mapview_common.c 2003/03/06 11:12:08
@@ -99,12 +99,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);
@@ -610,6 +605,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);
@@ -684,31 +681,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;
-
- /* 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);
- }
+ /* 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 - 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;
@@ -723,18 +714,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();
}
}
@@ -743,6 +736,8 @@
**************************************************************************/
void update_map_canvas_visible(void)
{
+ dirty_all();
+
if (is_isometric) {
/* just find a big rectangle that includes the whole visible area. The
invisible tiles will not be drawn. */
@@ -759,8 +754,6 @@
}
show_city_descriptions();
-
- flush_mapcanvas(0, 0, mapview_canvas.width, mapview_canvas.height);
}
/**************************************************************************
@@ -833,10 +826,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) {
@@ -845,12 +838,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);
}
}
}
@@ -882,6 +875,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))) {
@@ -1086,6 +1081,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.294
diff -u -r1.294 packhand.c
--- client/packhand.c 2003/03/06 09:11:18 1.294
+++ client/packhand.c 2003/03/06 11:12:10
@@ -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();
@@ -1705,14 +1707,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;
@@ -1723,7 +1725,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.163
diff -u -r1.163 mapview.c
--- client/gui-gtk/mapview.c 2003/03/06 09:35:11 1.163
+++ client/gui-gtk/mapview.c 2003/03/06 11:12:11
@@ -756,6 +756,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.51
diff -u -r1.51 mapview.c
--- client/gui-gtk-2.0/mapview.c 2003/03/06 09:35:11 1.51
+++ client/gui-gtk-2.0/mapview.c 2003/03/06 11:12:11
@@ -794,6 +794,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.60
diff -u -r1.60 mapview.c
--- client/gui-mui/mapview.c 2003/03/06 09:35:11 1.60
+++ client/gui-mui/mapview.c 2003/03/06 11:12:12
@@ -427,6 +427,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.20
diff -u -r1.20 gui_main.c
--- client/gui-sdl/gui_main.c 2003/03/01 12:11:19 1.20
+++ client/gui-sdl/gui_main.c 2003/03/06 11:12:12
@@ -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;
}
@@ -660,6 +665,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;
update_city_text_in_refresh_tile = FALSE;
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/03/06 11:12:12
@@ -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.36
diff -u -r1.36 mapview.c
--- client/gui-sdl/mapview.c 2003/03/06 09:35:11 1.36
+++ client/gui-sdl/mapview.c 2003/03/06 11:12:13
@@ -224,6 +224,40 @@
}
}
+static bool is_flush_queued = FALSE;
+
+/**************************************************************************
+ A callback invoked as a result of a FLUSH event, this function simply
+ flushes the mapview canvas.
+**************************************************************************/
+void unqueue_flush(void)
+{
+ is_flush_queued = FALSE;
+ flush_dirty();
+}
+
+/**************************************************************************
+ Called when a region is marked dirty, this function queues a flush event
+ to be handled later by SDL. 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) {
+ if (SDL_PushEvent(&flush_user_event) == 0) {
+ is_flush_queued = TRUE;
+ } else {
+ /* We don't want to set is_flush_queued in this case, since then
+ * the flush code would simply stop working. But this means the
+ * below message may be repeated many times. */
+ freelog(LOG_ERROR,
+ _("The SDL event buffer is full; you may see drawing errors\n"
+ "as a result. If you see this message often, please\n"
+ "report it to freeciv-dev@xxxxxxxxxxx."));
+ }
+ }
+}
+
/**************************************************************************
Save Flush area used by "end" flush.
**************************************************************************/
@@ -233,6 +267,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();
}
}
@@ -243,6 +278,7 @@
{
if ((Main.rects_count < RECT_LIMIT) && correct_rect_region(&Rect)) {
Main.rects[Main.rects_count++] = Rect;
+ queue_flush();
}
}
@@ -252,6 +288,7 @@
void dirty_all(void)
{
Main.rects_count = RECT_LIMIT;
+ queue_flush();
}
/**************************************************************************
@@ -269,7 +306,6 @@
**************************************************************************/
void flush_dirty(void)
{
-
if(!Main.rects_count) {
return;
}
Index: client/gui-sdl/mapview.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-sdl/mapview.h,v
retrieving revision 1.6
diff -u -r1.6 mapview.h
--- client/gui-sdl/mapview.h 2003/02/28 12:51:01 1.6
+++ client/gui-sdl/mapview.h 2003/03/06 11:12:13
@@ -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);
void flush_all(void);
Index: client/gui-stub/mapview.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-stub/mapview.c,v
retrieving revision 1.31
diff -u -r1.31 mapview.c
--- client/gui-stub/mapview.c 2003/03/06 09:35:11 1.31
+++ client/gui-stub/mapview.c 2003/03/06 11:12:13
@@ -206,6 +206,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.63
diff -u -r1.63 mapview.c
--- client/gui-win32/mapview.c 2003/03/06 09:35:11 1.63
+++ client/gui-win32/mapview.c 2003/03/06 11:12:14
@@ -507,6 +507,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.130
diff -u -r1.130 mapview.c
--- client/gui-xaw/mapview.c 2003/03/06 09:35:11 1.130
+++ client/gui-xaw/mapview.c 2003/03/06 11:12:15
@@ -665,6 +665,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.36
diff -u -r1.36 mapview_g.h
--- client/include/mapview_g.h 2003/03/06 09:35:12 1.36
+++ client/include/mapview_g.h 2003/03/06 11:12:15
@@ -52,6 +52,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);
|
|