summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/clear_cmd.cpp1
-rw-r--r--src/console_cmds.cpp2
-rw-r--r--src/genworld.cpp80
-rw-r--r--src/genworld.h5
-rw-r--r--src/genworld_gui.cpp26
-rw-r--r--src/gfx.cpp20
-rw-r--r--src/landscape.cpp6
-rw-r--r--src/network/network_content_gui.cpp3
-rw-r--r--src/newgrf_config.cpp33
-rw-r--r--src/newgrf_gui.cpp2
-rw-r--r--src/openttd.cpp40
-rw-r--r--src/openttd.h2
-rw-r--r--src/progress.cpp21
-rw-r--r--src/progress.h18
-rw-r--r--src/thread.h5
-rw-r--r--src/tree_cmd.cpp1
-rw-r--r--src/video/dedicated_v.cpp14
-rw-r--r--src/video/video_driver.cpp19
-rw-r--r--src/video/video_driver.hpp2
19 files changed, 90 insertions, 210 deletions
diff --git a/src/clear_cmd.cpp b/src/clear_cmd.cpp
index 6d3167e5a..403631312 100644
--- a/src/clear_cmd.cpp
+++ b/src/clear_cmd.cpp
@@ -338,6 +338,7 @@ void GenerateClearTile()
TileIndex tile_new;
SetClearGroundDensity(tile, CLEAR_ROCKS, 3);
+ MarkTileDirtyByTile(tile);
do {
if (--j == 0) goto get_out;
tile_new = tile + TileOffsByDiagDir((DiagDirection)GB(Random(), 0, 2));
diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp
index 8a7a5e399..18c4263f5 100644
--- a/src/console_cmds.cpp
+++ b/src/console_cmds.cpp
@@ -1340,7 +1340,7 @@ DEF_CONSOLE_CMD(ConRescanNewGRF)
return true;
}
- ScanNewGRFFiles(nullptr);
+ RequestNewGRFScan();
return true;
}
diff --git a/src/genworld.cpp b/src/genworld.cpp
index c76fe309d..03fa08819 100644
--- a/src/genworld.cpp
+++ b/src/genworld.cpp
@@ -59,18 +59,10 @@ GenWorldInfo _gw;
/** Whether we are generating the map or not. */
bool _generating_world;
-/**
- * Tells if the world generation is done in a thread or not.
- * @return the 'threaded' status
- */
-bool IsGenerateWorldThreaded()
-{
- return _gw.threaded && !_gw.quit_thread;
-}
+class AbortGenerateWorldSignal { };
/**
- * Clean up the 'mess' of generation. That is, show windows again, reset
- * thread variables, and delete the progress window.
+ * Generation is done; show windows again and delete the progress window.
*/
static void CleanupGeneration()
{
@@ -78,11 +70,10 @@ static void CleanupGeneration()
SetMouseCursorBusy(false);
/* Show all vital windows again, because we have hidden them */
- if (_gw.threaded && _game_mode != GM_MENU) ShowVitalWindows();
+ if (_game_mode != GM_MENU) ShowVitalWindows();
SetModalProgress(false);
_gw.proc = nullptr;
_gw.abortp = nullptr;
- _gw.threaded = false;
DeleteWindowByClass(WC_MODAL_PROGRESS);
ShowFirstError();
@@ -97,10 +88,8 @@ static void _GenerateWorld()
/* Make sure everything is done via OWNER_NONE. */
Backup<CompanyID> _cur_company(_current_company, OWNER_NONE, FILE_LINE);
- std::unique_lock<std::mutex> lock(_modal_progress_work_mutex, std::defer_lock);
try {
_generating_world = true;
- lock.lock();
if (_network_dedicated) DEBUG(net, 1, "Generating map, please wait...");
/* Set the Random() seed to generation_seed so we produce the same map with the same seed */
if (_settings_game.game_creation.generation_seed == GENERATE_NEW_SEED) _settings_game.game_creation.generation_seed = _settings_newgame.game_creation.generation_seed = InteractiveRandom();
@@ -136,14 +125,7 @@ static void _GenerateWorld()
/* Only generate towns, tree and industries in newgame mode. */
if (_game_mode != GM_EDITOR) {
if (!GenerateTowns(_settings_game.economy.town_layout)) {
- _cur_company.Restore();
HandleGeneratingWorldAbortion();
- BasePersistentStorageArray::SwitchMode(PSM_LEAVE_GAMELOOP);
- if (_network_dedicated) {
- /* Exit the game to prevent a return to main menu. */
- DEBUG(net, 0, "Generating map failed, aborting");
- _exit_game = true;
- }
return;
}
GenerateIndustries();
@@ -200,7 +182,6 @@ static void _GenerateWorld()
IncreaseGeneratingWorldProgress(GWP_GAME_START);
CleanupGeneration();
- lock.unlock();
ShowNewGRFError();
@@ -212,11 +193,19 @@ static void _GenerateWorld()
seprintf(name, lastof(name), "dmp_cmds_%08x_%08x.sav", _settings_game.game_creation.generation_seed, _date);
SaveOrLoad(name, SLO_SAVE, DFT_GAME_FILE, AUTOSAVE_DIR, false);
}
- } catch (...) {
+ } catch (AbortGenerateWorldSignal&) {
+ CleanupGeneration();
+
BasePersistentStorageArray::SwitchMode(PSM_LEAVE_GAMELOOP, true);
if (_cur_company.IsValid()) _cur_company.Restore();
- _generating_world = false;
- throw;
+
+ if (_network_dedicated) {
+ /* Exit the game to prevent a return to main menu. */
+ DEBUG(net, 0, "Generating map failed, aborting");
+ _exit_game = true;
+ } else {
+ SwitchToMode(_switch_mode);
+ }
}
}
@@ -241,23 +230,6 @@ void GenerateWorldSetAbortCallback(GWAbortProc *proc)
}
/**
- * This will wait for the thread to finish up his work. It will not continue
- * till the work is done.
- */
-void WaitTillGeneratedWorld()
-{
- if (!_gw.thread.joinable()) return;
-
- _modal_progress_work_mutex.unlock();
- _modal_progress_paint_mutex.unlock();
- _gw.quit_thread = true;
- _gw.thread.join();
- _gw.threaded = false;
- _modal_progress_work_mutex.lock();
- _modal_progress_paint_mutex.lock();
-}
-
-/**
* Initializes the abortion process
*/
void AbortGeneratingWorld()
@@ -284,11 +256,7 @@ void HandleGeneratingWorldAbortion()
if (_gw.abortp != nullptr) _gw.abortp();
- CleanupGeneration();
-
- if (_gw.thread.joinable() && _gw.thread.get_id() == std::this_thread::get_id()) throw OTTDThreadExitSignal();
-
- SwitchToMode(_switch_mode);
+ throw AbortGenerateWorldSignal();
}
/**
@@ -308,8 +276,6 @@ void GenerateWorld(GenWorldMode mode, uint size_x, uint size_y, bool reset_setti
_gw.abort = false;
_gw.abortp = nullptr;
_gw.lc = _local_company;
- _gw.quit_thread = false;
- _gw.threaded = true;
/* This disables some commands and stuff */
SetLocalCompany(COMPANY_SPECTATOR);
@@ -328,28 +294,16 @@ void GenerateWorld(GenWorldMode mode, uint size_x, uint size_y, bool reset_setti
SetupColoursAndInitialWindow();
SetObjectToPlace(SPR_CURSOR_ZZZ, PAL_NONE, HT_NONE, WC_MAIN_WINDOW, 0);
- if (_gw.thread.joinable()) _gw.thread.join();
-
- if (!UseThreadedModelProgress() || !VideoDriver::GetInstance()->HasGUI() || !StartNewThread(&_gw.thread, "ottd:genworld", &_GenerateWorld)) {
- DEBUG(misc, 1, "Cannot create genworld thread, reverting to single-threaded mode");
- _gw.threaded = false;
- _modal_progress_work_mutex.unlock();
- _GenerateWorld();
- _modal_progress_work_mutex.lock();
- return;
- }
-
UnshowCriticalError();
- /* Remove any open window */
DeleteAllNonVitalWindows();
- /* Hide vital windows, because we don't allow to use them */
HideVitalWindows();
- /* Don't show the dialog if we don't have a thread */
ShowGenerateWorldProgress();
/* Centre the view on the map */
if (FindWindowById(WC_MAIN_WINDOW, 0) != nullptr) {
ScrollMainWindowToTile(TileXY(MapSizeX() / 2, MapSizeY() / 2), true);
}
+
+ _GenerateWorld();
}
diff --git a/src/genworld.h b/src/genworld.h
index 801479712..e780ed169 100644
--- a/src/genworld.h
+++ b/src/genworld.h
@@ -52,15 +52,12 @@ typedef void GWAbortProc(); ///< Called when genworld is aborted
/** Properties of current genworld process */
struct GenWorldInfo {
bool abort; ///< Whether to abort the thread ASAP
- bool quit_thread; ///< Do we want to quit the active thread
- bool threaded; ///< Whether we run _GenerateWorld threaded
GenWorldMode mode; ///< What mode are we making a world in
CompanyID lc; ///< The local_company before generating
uint size_x; ///< X-size of the map
uint size_y; ///< Y-size of the map
GWDoneProc *proc; ///< Proc that is called when done (can be nullptr)
GWAbortProc *abortp; ///< Proc that is called when aborting (can be nullptr)
- std::thread thread; ///< The thread we are in (joinable if a thread was created)
};
/** Current stage of world generation process */
@@ -81,10 +78,8 @@ enum GenWorldProgress {
};
/* genworld.cpp */
-bool IsGenerateWorldThreaded();
void GenerateWorldSetCallback(GWDoneProc *proc);
void GenerateWorldSetAbortCallback(GWAbortProc *proc);
-void WaitTillGeneratedWorld();
void GenerateWorld(GenWorldMode mode, uint size_x, uint size_y, bool reset_settings = true);
void AbortGeneratingWorld();
bool IsGeneratingWorldAborted();
diff --git a/src/genworld_gui.cpp b/src/genworld_gui.cpp
index bf4d327a7..f26d43ac3 100644
--- a/src/genworld_gui.cpp
+++ b/src/genworld_gui.cpp
@@ -29,6 +29,7 @@
#include "error.h"
#include "newgrf_townname.h"
#include "townname_type.h"
+#include "video/video_driver.hpp"
#include "widgets/genworld_widget.h"
@@ -1312,10 +1313,10 @@ static void _SetGeneratingWorldProgress(GenWorldProgress cls, uint progress, uin
static_assert(lengthof(percent_table) == GWP_CLASS_COUNT + 1);
assert(cls < GWP_CLASS_COUNT);
- /* Do not run this function if we aren't in a thread */
- if (!IsGenerateWorldThreaded() && !_network_dedicated) return;
-
- if (IsGeneratingWorldAborted()) HandleGeneratingWorldAbortion();
+ if (IsGeneratingWorldAborted()) {
+ HandleGeneratingWorldAbortion();
+ return;
+ }
if (total == 0) {
assert(_gws.cls == _generation_class_table[cls]);
@@ -1328,10 +1329,6 @@ static void _SetGeneratingWorldProgress(GenWorldProgress cls, uint progress, uin
_gws.percent = percent_table[cls];
}
- /* Don't update the screen too often. So update it once in every once in a while... */
- if (!_network_dedicated && std::chrono::steady_clock::now() < _gws.next_update) return;
- _gws.next_update = std::chrono::steady_clock::now() + std::chrono::milliseconds(MODAL_PROGRESS_REDRAW_TIMEOUT);
-
/* Percentage is about the number of completed tasks, so 'current - 1' */
_gws.percent = percent_table[cls] + (percent_table[cls + 1] - percent_table[cls]) * (_gws.current == 0 ? 0 : _gws.current - 1) / _gws.total;
@@ -1350,21 +1347,12 @@ static void _SetGeneratingWorldProgress(GenWorldProgress cls, uint progress, uin
DEBUG(net, 1, "Map generation percentage complete: %d", _gws.percent);
last_percent = _gws.percent;
- /* Don't continue as dedicated never has a thread running */
return;
}
SetWindowDirty(WC_MODAL_PROGRESS, 0);
- MarkWholeScreenDirty();
-
- /* Release the rights to the map generator, and acquire the rights to the
- * paint thread. The 'other' thread already has the paint thread rights so
- * this ensures us that we are waiting until the paint thread is done
- * before we reacquire the mapgen rights */
- _modal_progress_work_mutex.unlock();
- _modal_progress_paint_mutex.lock();
- _modal_progress_work_mutex.lock();
- _modal_progress_paint_mutex.unlock();
+
+ VideoDriver::GetInstance()->GameLoopPause();
}
/**
diff --git a/src/gfx.cpp b/src/gfx.cpp
index 3189b8d96..6bcee66b1 100644
--- a/src/gfx.cpp
+++ b/src/gfx.cpp
@@ -1470,26 +1470,6 @@ void DrawDirtyBlocks()
int x;
int y;
- if (HasModalProgress()) {
- /* We are generating the world, so release our rights to the map and
- * painting while we are waiting a bit. */
- _modal_progress_paint_mutex.unlock();
- _modal_progress_work_mutex.unlock();
-
- /* Wait a while and hope the modal gives us a bit of time to draw the GUI. */
- if (!IsFirstModalProgressLoop()) CSleep(MODAL_PROGRESS_REDRAW_TIMEOUT);
-
- /* Modal progress thread may need blitter access while we are waiting for it. */
- _modal_progress_paint_mutex.lock();
- _modal_progress_work_mutex.lock();
-
- /* When we ended with the modal progress, do not draw the blocks.
- * Simply let the next run do so, otherwise we would be loading
- * the new state (and possibly change the blitter) when we hold
- * the drawing lock, which we must not do. */
- if (_switch_mode != SM_NONE && !HasModalProgress()) return;
- }
-
y = 0;
do {
x = 0;
diff --git a/src/landscape.cpp b/src/landscape.cpp
index 80ba516ac..ab6ba59f0 100644
--- a/src/landscape.cpp
+++ b/src/landscape.cpp
@@ -1062,6 +1062,7 @@ static bool MakeLake(TileIndex tile, void *user_data)
TileIndex t2 = tile + TileOffsByDiagDir(d);
if (IsWaterTile(t2)) {
MakeRiver(tile, Random());
+ MarkTileDirtyByTile(tile);
/* Remove desert directly around the river tile. */
TileIndex t = tile;
CircularTileSearch(&t, RIVER_OFFSET_DESERT_DISTANCE, RiverModifyDesertZone, nullptr);
@@ -1135,6 +1136,7 @@ static void River_FoundEndNode(AyStar *aystar, OpenListNode *current)
TileIndex tile = path->node.tile;
if (!IsWaterTile(tile)) {
MakeRiver(tile, Random());
+ MarkTileDirtyByTile(tile);
/* Remove desert directly around the river tile. */
CircularTileSearch(&tile, RIVER_OFFSET_DESERT_DISTANCE, RiverModifyDesertZone, nullptr);
}
@@ -1247,6 +1249,7 @@ static bool FlowRiver(TileIndex spring, TileIndex begin)
DistanceManhattan(spring, lakeCenter) > _settings_game.game_creation.min_river_length) {
end = lakeCenter;
MakeRiver(lakeCenter, Random());
+ MarkTileDirtyByTile(lakeCenter);
/* Remove desert directly around the river tile. */
CircularTileSearch(&lakeCenter, RIVER_OFFSET_DESERT_DISTANCE, RiverModifyDesertZone, nullptr);
lakeCenter = end;
@@ -1368,8 +1371,11 @@ void GenerateLandscape(byte mode)
/* Do not call IncreaseGeneratingWorldProgress() before FixSlopes(),
* it allows screen redraw. Drawing of broken slopes crashes the game */
FixSlopes();
+ MarkWholeScreenDirty();
IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
+
ConvertGroundTilesIntoWaterTiles();
+ MarkWholeScreenDirty();
IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
if (_settings_game.game_creation.landscape == LT_TROPIC) CreateDesertOrRainForest();
diff --git a/src/network/network_content_gui.cpp b/src/network/network_content_gui.cpp
index 13e162b07..466279125 100644
--- a/src/network/network_content_gui.cpp
+++ b/src/network/network_content_gui.cpp
@@ -15,6 +15,7 @@
#include "../ai/ai.hpp"
#include "../game/game.hpp"
#include "../base_media_base.h"
+#include "../openttd.h"
#include "../sortlist_type.h"
#include "../stringfilter_type.h"
#include "../querystring_gui.h"
@@ -236,7 +237,7 @@ public:
break;
case CONTENT_TYPE_NEWGRF:
- ScanNewGRFFiles(nullptr);
+ RequestNewGRFScan();
break;
case CONTENT_TYPE_SCENARIO:
diff --git a/src/newgrf_config.cpp b/src/newgrf_config.cpp
index e56f878bd..911d266df 100644
--- a/src/newgrf_config.cpp
+++ b/src/newgrf_config.cpp
@@ -635,20 +635,12 @@ bool GRFFileScanner::AddFile(const std::string &filename, size_t basepath_length
}
this->num_scanned++;
- if (std::chrono::steady_clock::now() >= this->next_update) {
- this->next_update = std::chrono::steady_clock::now() + std::chrono::milliseconds(MODAL_PROGRESS_REDRAW_TIMEOUT);
- _modal_progress_work_mutex.unlock();
- _modal_progress_paint_mutex.lock();
-
- const char *name = nullptr;
- if (c->name != nullptr) name = GetGRFStringFromGRFText(c->name);
- if (name == nullptr) name = c->filename;
- UpdateNewGRFScanStatus(this->num_scanned, name);
-
- _modal_progress_work_mutex.lock();
- _modal_progress_paint_mutex.unlock();
- }
+ const char *name = nullptr;
+ if (c->name != nullptr) name = GetGRFStringFromGRFText(c->name);
+ if (name == nullptr) name = c->filename;
+ UpdateNewGRFScanStatus(this->num_scanned, name);
+ VideoDriver::GetInstance()->GameLoopPause();
if (!added) {
/* File couldn't be opened, or is either not a NewGRF or is a
@@ -676,8 +668,6 @@ static bool GRFSorter(GRFConfig * const &c1, GRFConfig * const &c2)
*/
void DoScanNewGRFFiles(NewGRFScanCallback *callback)
{
- std::unique_lock<std::mutex> lock_work(_modal_progress_work_mutex);
-
ClearGRFConfigList(&_all_grfs);
TarScanner::DoScan(TarScanner::NEWGRF);
@@ -709,9 +699,6 @@ void DoScanNewGRFFiles(NewGRFScanCallback *callback)
NetworkAfterNewGRFScan();
}
- lock_work.unlock();
- std::lock_guard<std::mutex> lock_paint(_modal_progress_paint_mutex);
-
/* Yes... these are the NewGRF windows */
InvalidateWindowClassesData(WC_SAVELOAD, 0, true);
InvalidateWindowData(WC_GAME_OPTIONS, WN_GAME_OPTIONS_NEWGRF_STATE, GOID_NEWGRF_RESCANNED, true);
@@ -733,15 +720,7 @@ void ScanNewGRFFiles(NewGRFScanCallback *callback)
/* Only then can we really start, especially by marking the whole screen dirty. Get those other windows hidden!. */
MarkWholeScreenDirty();
- if (!UseThreadedModelProgress() || !VideoDriver::GetInstance()->HasGUI() || !StartNewThread(nullptr, "ottd:newgrf-scan", &DoScanNewGRFFiles, (NewGRFScanCallback *)callback)) { // Without the seemingly superfluous cast, strange compiler errors ensue.
- _modal_progress_work_mutex.unlock();
- _modal_progress_paint_mutex.unlock();
- DoScanNewGRFFiles(callback);
- _modal_progress_paint_mutex.lock();
- _modal_progress_work_mutex.lock();
- } else {
- UpdateNewGRFScanStatus(0, nullptr);
- }
+ DoScanNewGRFFiles(callback);
}
/**
diff --git a/src/newgrf_gui.cpp b/src/newgrf_gui.cpp
index 9e340654c..4e63eafbe 100644
--- a/src/newgrf_gui.cpp
+++ b/src/newgrf_gui.cpp
@@ -1127,7 +1127,7 @@ struct NewGRFWindow : public Window, NewGRFScanCallback {
case WID_NS_RESCAN_FILES:
case WID_NS_RESCAN_FILES2:
- ScanNewGRFFiles(this);
+ RequestNewGRFScan(this);
break;
}
}
diff --git a/src/openttd.cpp b/src/openttd.cpp
index 3397e4f0e..2d37c8e3a 100644
--- a/src/openttd.cpp
+++ b/src/openttd.cpp
@@ -91,6 +91,8 @@ extern void ShowOSErrorBox(const char *buf, bool system);
extern std::string _config_file;
bool _save_config = false;
+bool _request_newgrf_scan = false;
+NewGRFScanCallback *_request_newgrf_scan_callback = nullptr;
/**
* Error handling for fatal user errors.
@@ -345,7 +347,6 @@ static void LoadIntroGame(bool load_newgrfs = true)
/* Load the default opening screen savegame */
if (SaveOrLoad("opntitle.dat", SLO_LOAD, DFT_GAME_FILE, BASESET_DIR) != SL_OK) {
GenerateWorld(GWM_EMPTY, 64, 64); // if failed loading, make empty world.
- WaitTillGeneratedWorld();
SetLocalCompany(COMPANY_SPECTATOR);
} else {
SetLocalCompany(COMPANY_FIRST);
@@ -559,9 +560,6 @@ int openttd_main(int argc, char *argv[])
extern bool _dedicated_forks;
_dedicated_forks = false;
- std::unique_lock<std::mutex> modal_work_lock(_modal_progress_work_mutex, std::defer_lock);
- std::unique_lock<std::mutex> modal_paint_lock(_modal_progress_paint_mutex, std::defer_lock);
-
_game_mode = GM_MENU;
_switch_mode = SM_MENU;
@@ -828,30 +826,17 @@ int openttd_main(int argc, char *argv[])
if (musicdriver.empty() && !_ini_musicdriver.empty()) musicdriver = _ini_musicdriver;
DriverFactoryBase::SelectDriver(musicdriver, Driver::DT_MUSIC);
- /* Take our initial lock on whatever we might want to do! */
- try {
- modal_work_lock.lock();
- modal_paint_lock.lock();
- } catch (const std::system_error&) {
- /* If there is some error we assume that threads aren't usable on the system we run. */
- extern bool _use_threaded_modal_progress; // From progress.cpp
- _use_threaded_modal_progress = false;
- }
-
GenerateWorld(GWM_EMPTY, 64, 64); // Make the viewport initialization happy
- WaitTillGeneratedWorld();
-
LoadIntroGame(false);
CheckForMissingGlyphs();
/* ScanNewGRFFiles now has control over the scanner. */
- ScanNewGRFFiles(scanner.release());
+ RequestNewGRFScan(scanner.release());
VideoDriver::GetInstance()->MainLoop();
WaitTillSaved();
- WaitTillGeneratedWorld(); // Make sure any generate world threads have been joined.
/* only save config if we have to */
if (_save_config) {
@@ -1460,6 +1445,19 @@ static void DoAutosave()
}
}
+/**
+ * Request a new NewGRF scan. This will be executed on the next game-tick.
+ * This is mostly needed to ensure NewGRF scans (which are blocking) are
+ * done in the game-thread, and not in the draw-thread (which most often
+ * triggers this request).
+ * @param callback Optional callback to call when NewGRF scan is completed.
+ */
+void RequestNewGRFScan(NewGRFScanCallback *callback)
+{
+ _request_newgrf_scan = true;
+ _request_newgrf_scan_callback = callback;
+}
+
void GameLoop()
{
if (_game_mode == GM_BOOTSTRAP) {
@@ -1468,6 +1466,12 @@ void GameLoop()
return;
}
+ if (_request_newgrf_scan) {
+ ScanNewGRFFiles(_request_newgrf_scan_callback);
+ _request_newgrf_scan = false;
+ _request_newgrf_scan_callback = nullptr;
+ }
+
ProcessAsyncSaveFinish();
/* autosave game? */
diff --git a/src/openttd.h b/src/openttd.h
index 62651fe7f..38c7f8064 100644
--- a/src/openttd.h
+++ b/src/openttd.h
@@ -81,4 +81,6 @@ void HandleExitGameRequest();
void SwitchToMode(SwitchMode new_mode);
+void RequestNewGRFScan(struct NewGRFScanCallback *callback = nullptr);
+
#endif /* OPENTTD_H */
diff --git a/src/progress.cpp b/src/progress.cpp
index e45e5db07..6444d8a85 100644
--- a/src/progress.cpp
+++ b/src/progress.cpp
@@ -14,33 +14,12 @@
/** Are we in a modal progress or not? */
bool _in_modal_progress = false;
-bool _first_in_modal_loop = false;
-/** Threading usable for modal progress? */
-bool _use_threaded_modal_progress = true;
-/** Rights for the performing work. */
-std::mutex _modal_progress_work_mutex;
-/** Rights for the painting. */
-std::mutex _modal_progress_paint_mutex;
/**
* Set the modal progress state.
- * @note Makes IsFirstModalProgressLoop return true for the next call.
* @param state The new state; are we modal or not?
*/
void SetModalProgress(bool state)
{
_in_modal_progress = state;
- _first_in_modal_loop = true;
-}
-
-/**
- * Check whether this is the first modal progress loop.
- * @note Set by SetModalProgress, unset by calling this method.
- * @return True if this is the first loop.
- */
-bool IsFirstModalProgressLoop()
-{
- bool ret = _first_in_modal_loop;
- _first_in_modal_loop = false;
- return ret;
}
diff --git a/src/progress.h b/src/progress.h
index 59a61c678..765020635 100644
--- a/src/progress.h
+++ b/src/progress.h
@@ -10,10 +10,6 @@
#ifndef PROGRESS_H
#define PROGRESS_H
-#include <mutex>
-
-static const uint MODAL_PROGRESS_REDRAW_TIMEOUT = 200; ///< Timeout between redraws
-
/**
* Check if we are currently in a modal progress state.
* @return Are we in the modal state?
@@ -24,20 +20,6 @@ static inline bool HasModalProgress()
return _in_modal_progress;
}
-/**
- * Check if we can use a thread for modal progress.
- * @return Threading usable?
- */
-static inline bool UseThreadedModelProgress()
-{
- extern bool _use_threaded_modal_progress;
- return _use_threaded_modal_progress;
-}
-
-bool IsFirstModalProgressLoop();
void SetModalProgress(bool state);
-extern std::mutex _modal_progress_work_mutex;
-extern std::mutex _modal_progress_paint_mutex;
-
#endif /* PROGRESS_H */
diff --git a/src/thread.h b/src/thread.h
index f4a16d4e0..f45694930 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -14,10 +14,6 @@
#include <system_error>
#include <thread>
-/** Signal used for signalling we knowingly want to end the thread. */
-class OTTDThreadExitSignal { };
-
-
/**
* Sleep on the current thread for a defined time.
* @param milliseconds Time to sleep for in milliseconds.
@@ -54,7 +50,6 @@ inline bool StartNewThread(std::thread *thr, const char *name, TFn&& _Fx, TArgs&
try {
/* Call user function with the given arguments. */
F(A...);
- } catch (OTTDThreadExitSignal&) {
} catch (...) {
NOT_REACHED();
}
diff --git a/src/tree_cmd.cpp b/src/tree_cmd.cpp
index e4ce1da14..c0865ffc6 100644
--- a/src/tree_cmd.cpp
+++ b/src/tree_cmd.cpp
@@ -164,6 +164,7 @@ static void PlaceTree(TileIndex tile, uint32 r)
if (tree != TREE_INVALID) {
PlantTreesOnTile(tile, tree, GB(r, 22, 2), std::min<byte>(GB(r, 16, 3), 6));
+ MarkTileDirtyByTile(tile);
/* Rerandomize ground, if neither snow nor shore */
TreeGround ground = GetTreeGround(tile);
diff --git a/src/video/dedicated_v.cpp b/src/video/dedicated_v.cpp
index ea1c14cff..e905a9d2c 100644
--- a/src/video/dedicated_v.cpp
+++ b/src/video/dedicated_v.cpp
@@ -251,19 +251,16 @@ void VideoDriver_Dedicated::MainLoop()
/* If SwitchMode is SM_LOAD_GAME, it means that the user used the '-g' options */
if (_switch_mode != SM_LOAD_GAME) {
StartNewGameWithoutGUI(GENERATE_NEW_SEED);
- SwitchToMode(_switch_mode);
- _switch_mode = SM_NONE;
} else {
- _switch_mode = SM_NONE;
/* First we need to test if the savegame can be loaded, else we will end up playing the
* intro game... */
- if (!SafeLoad(_file_to_saveload.name, _file_to_saveload.file_op, _file_to_saveload.detail_ftype, GM_NORMAL, BASE_DIR)) {
+ if (SaveOrLoad(_file_to_saveload.name, _file_to_saveload.file_op, _file_to_saveload.detail_ftype, BASE_DIR) == SL_ERROR) {
/* Loading failed, pop out.. */
DEBUG(net, 0, "Loading requested map failed, aborting");
- _networking = false;
+ return;
} else {
/* We can load this game, so go ahead */
- SwitchToMode(SM_LOAD_GAME);
+ _switch_mode = SM_LOAD_GAME;
}
}
@@ -271,11 +268,6 @@ void VideoDriver_Dedicated::MainLoop()
/* Done loading, start game! */
- if (!_networking) {
- DEBUG(net, 0, "Dedicated server could not be started, aborting");
- return;
- }
-
while (!_exit_game) {
if (!_dedicated_forks) DedicatedHandleKeyInput();
diff --git a/src/video/video_driver.cpp b/src/video/video_driver.cpp
index 1b7fc6a4b..bee67e1ea 100644
--- a/src/video/video_driver.cpp
+++ b/src/video/video_driver.cpp
@@ -56,6 +56,25 @@ void VideoDriver::GameThread()
}
}
+/**
+ * Pause the game-loop for a bit, releasing the game-state lock. This allows,
+ * if the draw-tick requested this, the drawing to happen.
+ */
+void VideoDriver::GameLoopPause()
+{
+ /* If we are not called from the game-thread, ignore this request. */
+ if (std::this_thread::get_id() != this->game_thread.get_id()) return;
+
+ this->game_state_mutex.unlock();
+
+ {
+ /* See GameThread() for more details on this lock. */
+ std::lock_guard<std::mutex> lock(this->game_thread_wait_mutex);
+ }
+
+ this->game_state_mutex.lock();
+}
+
/* static */ void VideoDriver::GameThreadThunk(VideoDriver *drv)
{
drv->GameThread();
diff --git a/src/video/video_driver.hpp b/src/video/video_driver.hpp
index 8c2b9d437..7a859565a 100644
--- a/src/video/video_driver.hpp
+++ b/src/video/video_driver.hpp
@@ -179,6 +179,8 @@ public:
this->change_blitter = new_blitter;
}
+ void GameLoopPause();
+
/**
* Get the currently active instance of the video driver.
*/