Reduce viewport invalidation area of signal state changes

This commit is contained in:
Jonathan G Rennison
2020-02-20 19:28:53 +00:00
parent b9eaef9fe1
commit 5240b46d1d
5 changed files with 74 additions and 15 deletions

View File

@@ -84,6 +84,7 @@ bool TryReserveRailTrackdir(TileIndex tile, Trackdir td, bool trigger_stations)
bool success = TryReserveRailTrack(tile, TrackdirToTrack(td), trigger_stations); bool success = TryReserveRailTrack(tile, TrackdirToTrack(td), trigger_stations);
if (success && HasPbsSignalOnTrackdir(tile, td)) { if (success && HasPbsSignalOnTrackdir(tile, td)) {
SetSignalStateByTrackdir(tile, td, SIGNAL_STATE_GREEN); SetSignalStateByTrackdir(tile, td, SIGNAL_STATE_GREEN);
MarkSingleSignalDirty(tile, td);
} }
return success; return success;
} }
@@ -183,6 +184,7 @@ void UnreserveRailTrackdir(TileIndex tile, Trackdir td)
{ {
if (HasPbsSignalOnTrackdir(tile, td)) { if (HasPbsSignalOnTrackdir(tile, td)) {
SetSignalStateByTrackdir(tile, td, SIGNAL_STATE_RED); SetSignalStateByTrackdir(tile, td, SIGNAL_STATE_RED);
MarkSingleSignalDirty(tile, td);
} }
UnreserveRailTrack(tile, TrackdirToTrack(td)); UnreserveRailTrack(tile, TrackdirToTrack(td));
} }

View File

@@ -456,6 +456,8 @@ static inline Money SignalMaintenanceCost(uint32 num)
return (_price[PR_INFRASTRUCTURE_RAIL] * 15 * num * (1 + IntSqrt(num))) >> 8; // 1 bit fraction for the multiplier and 7 bits scaling. return (_price[PR_INFRASTRUCTURE_RAIL] * 15 * num * (1 + IntSqrt(num))) >> 8; // 1 bit fraction for the multiplier and 7 bits scaling.
} }
void MarkSingleSignalDirty(TileIndex tile, Trackdir td);
void DrawTrainDepotSprite(int x, int y, int image, RailType railtype); void DrawTrainDepotSprite(int x, int y, int image, RailType railtype);
int TicksToLeaveDepot(const Train *v); int TicksToLeaveDepot(const Train *v);

View File

@@ -2379,7 +2379,7 @@ static uint GetSaveSlopeZ(uint x, uint y, Track track)
return GetSlopePixelZ(x, y); return GetSlopePixelZ(x, y);
} }
void DrawSingleSignal(TileIndex tile, const RailtypeInfo *rti, Track track, SignalState condition, SignalOffsets image, uint pos, SignalType type, SignalVariant variant, bool show_restricted) static void GetSignalXY(TileIndex tile, uint pos, uint &x, uint &y)
{ {
bool side; bool side;
switch (_settings_game.construction.train_signal_side) { switch (_settings_game.construction.train_signal_side) {
@@ -2401,8 +2401,21 @@ void DrawSingleSignal(TileIndex tile, const RailtypeInfo *rti, Track track, Sign
} }
}; };
uint x = TileX(tile) * TILE_SIZE + SignalPositions[side][pos].x; x = TileX(tile) * TILE_SIZE + SignalPositions[side][pos].x;
uint y = TileY(tile) * TILE_SIZE + SignalPositions[side][pos].y; y = TileY(tile) * TILE_SIZE + SignalPositions[side][pos].y;
}
static bool _signal_sprite_oversized = false;
static const int SIGNAL_DIRTY_LEFT = 7 * ZOOM_LVL_BASE;
static const int SIGNAL_DIRTY_RIGHT = 7 * ZOOM_LVL_BASE;
static const int SIGNAL_DIRTY_TOP = 30 * ZOOM_LVL_BASE;
static const int SIGNAL_DIRTY_BOTTOM = 5 * ZOOM_LVL_BASE;
void DrawSingleSignal(TileIndex tile, const RailtypeInfo *rti, Track track, SignalState condition, SignalOffsets image, uint pos, SignalType type, SignalVariant variant, bool show_restricted)
{
uint x, y;
GetSignalXY(tile, pos, x, y);
SpriteID sprite; SpriteID sprite;
bool is_custom_sprite; bool is_custom_sprite;
@@ -2457,6 +2470,10 @@ void DrawSingleSignal(TileIndex tile, const RailtypeInfo *rti, Track track, Sign
} else { } else {
AddSortableSpriteToDraw(sprite, PAL_NONE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, GetSaveSlopeZ(x, y, track)); AddSortableSpriteToDraw(sprite, PAL_NONE, x, y, 1, 1, BB_HEIGHT_UNDER_BRIDGE, GetSaveSlopeZ(x, y, track));
} }
const Sprite *sp = GetSprite(sprite, ST_NORMAL);
if (sp->x_offs < -SIGNAL_DIRTY_LEFT || sp->x_offs + sp->width > SIGNAL_DIRTY_RIGHT || sp->y_offs < -SIGNAL_DIRTY_TOP || sp->y_offs + sp->height > SIGNAL_DIRTY_BOTTOM) {
_signal_sprite_oversized = true;
}
} }
static void DrawSingleSignal(TileIndex tile, const RailtypeInfo *rti, Track track, SignalState condition, SignalOffsets image, uint pos) static void DrawSingleSignal(TileIndex tile, const RailtypeInfo *rti, Track track, SignalState condition, SignalOffsets image, uint pos)
@@ -2468,6 +2485,44 @@ static void DrawSingleSignal(TileIndex tile, const RailtypeInfo *rti, Track trac
DrawSingleSignal(tile, rti, track, condition, image, pos, type, variant, show_restricted); DrawSingleSignal(tile, rti, track, condition, image, pos, type, variant, show_restricted);
} }
void MarkSingleSignalDirty(TileIndex tile, Trackdir td)
{
if (_signal_sprite_oversized || td >= TRACKDIR_END) {
MarkTileDirtyByTile(tile, ZOOM_LVL_DRAW_MAP);
return;
}
static const uint8 trackdir_to_pos[TRACKDIR_END] = {
8, // TRACKDIR_X_NE
10, // TRACKDIR_Y_SE
4, // TRACKDIR_UPPER_E
6, // TRACKDIR_LOWER_E
0, // TRACKDIR_LEFT_S
2, // TRACKDIR_RIGHT_S
0, // TRACKDIR_RVREV_NE
0, // TRACKDIR_RVREV_SE
9, // TRACKDIR_X_SW
11, // TRACKDIR_Y_NW
5, // TRACKDIR_UPPER_W
7, // TRACKDIR_LOWER_W
1, // TRACKDIR_LEFT_N
3, // TRACKDIR_RIGHT_N
0, // TRACKDIR_RVREV_SW
0, // TRACKDIR_RVREV_NW
};
uint x, y;
GetSignalXY(tile, trackdir_to_pos[td], x, y);
Point pt = RemapCoords(x, y, GetSaveSlopeZ(x, y, TrackdirToTrack(td)));
MarkAllViewportsDirty(
pt.x - SIGNAL_DIRTY_LEFT,
pt.y - SIGNAL_DIRTY_TOP,
pt.x + SIGNAL_DIRTY_RIGHT,
pt.y + SIGNAL_DIRTY_BOTTOM,
ZOOM_LVL_DRAW_MAP
);
}
static uint32 _drawtile_track_palette; static uint32 _drawtile_track_palette;

View File

@@ -583,7 +583,7 @@ static void UpdateSignalsAroundSegment(SigInfo info)
MarkDependencidesForUpdate(SignalReference(tile, track)); MarkDependencidesForUpdate(SignalReference(tile, track));
} }
SetSignalStateByTrackdir(tile, trackdir, newstate); SetSignalStateByTrackdir(tile, trackdir, newstate);
MarkTileDirtyByTile(tile, ZOOM_LVL_DRAW_MAP); MarkSingleSignalDirty(tile, trackdir);
} }
} }

View File

@@ -2822,7 +2822,7 @@ void FreeTrainTrackReservation(const Train *v, TileIndex origin, Trackdir orig_t
} else { } else {
/* Turn the signal back to red. */ /* Turn the signal back to red. */
SetSignalStateByTrackdir(tile, td, SIGNAL_STATE_RED); SetSignalStateByTrackdir(tile, td, SIGNAL_STATE_RED);
MarkTileDirtyByTile(tile, ZOOM_LVL_DRAW_MAP); MarkSingleSignalDirty(tile, td);
} }
} else if (HasSignalOnTrackdir(tile, ReverseTrackdir(td)) && IsOnewaySignal(tile, TrackdirToTrack(td))) { } else if (HasSignalOnTrackdir(tile, ReverseTrackdir(td)) && IsOnewaySignal(tile, TrackdirToTrack(td))) {
break; break;
@@ -3105,7 +3105,7 @@ static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir,
{ {
Track best_track = INVALID_TRACK; Track best_track = INVALID_TRACK;
bool do_track_reservation = _settings_game.pf.reserve_paths || force_res; bool do_track_reservation = _settings_game.pf.reserve_paths || force_res;
bool changed_signal = false; Trackdir changed_signal = INVALID_TRACKDIR;
assert((tracks & ~TRACK_BIT_MASK) == 0); assert((tracks & ~TRACK_BIT_MASK) == 0);
@@ -3138,8 +3138,8 @@ static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir,
ClrBit(v->flags, VRF_WAITING_RESTRICTION); ClrBit(v->flags, VRF_WAITING_RESTRICTION);
do_track_reservation = true; do_track_reservation = true;
changed_signal = true; changed_signal = TrackEnterdirToTrackdir(track, enterdir);
SetSignalStateByTrackdir(tile, TrackEnterdirToTrackdir(track, enterdir), SIGNAL_STATE_GREEN); SetSignalStateByTrackdir(tile, changed_signal, SIGNAL_STATE_GREEN);
} else if (!do_track_reservation) { } else if (!do_track_reservation) {
return track; return track;
} }
@@ -3154,7 +3154,7 @@ static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir,
if (res_dest.tile == INVALID_TILE) { if (res_dest.tile == INVALID_TILE) {
/* Reservation failed? */ /* Reservation failed? */
if (mark_stuck) MarkTrainAsStuck(v); if (mark_stuck) MarkTrainAsStuck(v);
if (changed_signal) SetSignalStateByTrackdir(tile, TrackEnterdirToTrackdir(best_track, enterdir), SIGNAL_STATE_RED); if (changed_signal != INVALID_TRACKDIR) SetSignalStateByTrackdir(tile, changed_signal, SIGNAL_STATE_RED);
return FindFirstTrack(tracks); return FindFirstTrack(tracks);
} }
if (res_dest.okay) { if (res_dest.okay) {
@@ -3165,7 +3165,7 @@ static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir,
if (!HasLongReservePbsSignalOnTrackdir(v, ft.m_new_tile, new_td)) { if (!HasLongReservePbsSignalOnTrackdir(v, ft.m_new_tile, new_td)) {
/* Got a valid reservation that ends at a safe target, quick exit. */ /* Got a valid reservation that ends at a safe target, quick exit. */
if (p_got_reservation != nullptr) *p_got_reservation = true; if (p_got_reservation != nullptr) *p_got_reservation = true;
if (changed_signal) MarkTileDirtyByTile(tile, ZOOM_LVL_DRAW_MAP); if (changed_signal != INVALID_TRACKDIR) MarkSingleSignalDirty(tile, changed_signal);
TryReserveRailTrack(v->tile, TrackdirToTrack(v->GetVehicleTrackdir())); TryReserveRailTrack(v->tile, TrackdirToTrack(v->GetVehicleTrackdir()));
return best_track; return best_track;
} }
@@ -3227,7 +3227,7 @@ static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir,
best_track = FindFirstTrack(res); best_track = FindFirstTrack(res);
TryReserveRailTrack(v->tile, TrackdirToTrack(v->GetVehicleTrackdir())); TryReserveRailTrack(v->tile, TrackdirToTrack(v->GetVehicleTrackdir()));
if (p_got_reservation != nullptr) *p_got_reservation = true; if (p_got_reservation != nullptr) *p_got_reservation = true;
if (changed_signal) MarkTileDirtyByTile(tile); if (changed_signal != INVALID_TRACKDIR) MarkSingleSignalDirty(tile, changed_signal);
} else { } else {
FreeTrainTrackReservation(v, origin.tile, origin.trackdir); FreeTrainTrackReservation(v, origin.tile, origin.trackdir);
if (mark_stuck) MarkTrainAsStuck(v); if (mark_stuck) MarkTrainAsStuck(v);
@@ -3259,7 +3259,7 @@ static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir,
FreeTrainTrackReservation(v, origin.tile, origin.trackdir); FreeTrainTrackReservation(v, origin.tile, origin.trackdir);
if (mark_stuck) MarkTrainAsStuck(v); if (mark_stuck) MarkTrainAsStuck(v);
got_reservation = false; got_reservation = false;
changed_signal = false; changed_signal = INVALID_TRACKDIR;
break; break;
} }
} }
@@ -3268,7 +3268,7 @@ static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir,
FreeTrainTrackReservation(v, origin.tile, origin.trackdir); FreeTrainTrackReservation(v, origin.tile, origin.trackdir);
if (mark_stuck) MarkTrainAsStuck(v); if (mark_stuck) MarkTrainAsStuck(v);
got_reservation = false; got_reservation = false;
changed_signal = false; changed_signal = INVALID_TRACKDIR;
} }
break; break;
} }
@@ -3287,7 +3287,7 @@ static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir,
TryReserveRailTrack(v->tile, TrackdirToTrack(v->GetVehicleTrackdir())); TryReserveRailTrack(v->tile, TrackdirToTrack(v->GetVehicleTrackdir()));
if (changed_signal) MarkTileDirtyByTile(tile, ZOOM_LVL_DRAW_MAP); if (changed_signal != INVALID_TRACKDIR) MarkSingleSignalDirty(tile, changed_signal);
if (p_got_reservation != nullptr) *p_got_reservation = got_reservation; if (p_got_reservation != nullptr) *p_got_reservation = got_reservation;
return best_track; return best_track;
@@ -4224,7 +4224,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
Trackdir tdir = TrackDirectionToTrackdir(track, chosen_dir); Trackdir tdir = TrackDirectionToTrackdir(track, chosen_dir);
if (v->IsFrontEngine() && HasPbsSignalOnTrackdir(gp.new_tile, tdir)) { if (v->IsFrontEngine() && HasPbsSignalOnTrackdir(gp.new_tile, tdir)) {
SetSignalStateByTrackdir(gp.new_tile, tdir, SIGNAL_STATE_RED); SetSignalStateByTrackdir(gp.new_tile, tdir, SIGNAL_STATE_RED);
MarkTileDirtyByTile(gp.new_tile); MarkSingleSignalDirty(gp.new_tile, tdir);
} }
/* Clear any track reservation when the last vehicle leaves the tile */ /* Clear any track reservation when the last vehicle leaves the tile */