From dfd9fbf873106a19146a126b5ea947c382d2ab23 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Sat, 26 Apr 2025 11:50:51 +0100 Subject: [PATCH] Codechange: Defer refreshing company finance windows. (#14111) During each game tick every cargo payment will issue an Invalidate of the status bar and company finance window. While this doesn't paint the window yet, it does need to search for open windows, and then mark a area of dirty blocks, which is done for every Invalidate. Instead, set a bit in a CompanyMask, and test these bits once after the game tick is complete. This reduces the amount of dirtying, and allows more specific widgets to be dirtied instead of the whole window. --- src/company_cmd.cpp | 24 +++++++++++++++++++++--- src/company_gui.h | 1 + src/openttd.cpp | 3 +++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index dbaaddb575..50cec4ee6a 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -203,16 +203,34 @@ static bool IsValidCompanyManagerFace(CompanyManagerFace cmf) return true; } +static CompanyMask _dirty_company_finances{}; ///< Bitmask of compamy finances that should be marked dirty. + /** - * Refresh all windows owned by a company. + * Mark all finance windows owned by a company as needing a refresh. + * The actual refresh is deferred until the end of the gameloop to reduce duplicated work. * @param company Company that changed, and needs its windows refreshed. */ void InvalidateCompanyWindows(const Company *company) { CompanyID cid = company->index; + _dirty_company_finances.Set(cid); +} - if (cid == _local_company) SetWindowWidgetDirty(WC_STATUS_BAR, 0, WID_S_RIGHT); - SetWindowDirty(WC_FINANCES, cid); +/** + * Refresh all company finance windows previously marked dirty. + */ +void InvalidateCompanyWindows() +{ + for (CompanyID cid : _dirty_company_finances) { + if (cid == _local_company) SetWindowWidgetDirty(WC_STATUS_BAR, 0, WID_S_RIGHT); + Window *w = FindWindowById(WC_FINANCES, cid); + if (w != nullptr) { + w->SetWidgetDirty(WID_CF_EXPS_PRICE3); + w->SetWidgetDirty(WID_CF_OWN_VALUE); + w->SetWidgetDirty(WID_CF_BALANCE_VALUE); + } + } + _dirty_company_finances = {}; } /** diff --git a/src/company_gui.h b/src/company_gui.h index f6149b05fb..0e951eb5c7 100644 --- a/src/company_gui.h +++ b/src/company_gui.h @@ -23,6 +23,7 @@ void ShowCompanyFinances(CompanyID company); void ShowCompany(CompanyID company); void InvalidateCompanyWindows(const Company *c); +void InvalidateCompanyWindows(); void CloseCompanyWindows(CompanyID company); void DirtyCompanyInfrastructureWindows(CompanyID company); diff --git a/src/openttd.cpp b/src/openttd.cpp index d095f23b01..617c9cafc4 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -27,6 +27,7 @@ #include "saveload/saveload.h" #include "company_cmd.h" #include "company_func.h" +#include "company_gui.h" #include "command_func.h" #include "news_func.h" #include "fios.h" @@ -1229,6 +1230,7 @@ void StateGameLoop() CallWindowGameTickEvent(); NewsLoop(); + InvalidateCompanyWindows(); } else { if (_debug_desync_level > 2 && TimerGameEconomy::date_fract == 0 && (TimerGameEconomy::date.base() & 0x1F) == 0) { /* Save the desync savegame if needed. */ @@ -1265,6 +1267,7 @@ void StateGameLoop() CallWindowGameTickEvent(); NewsLoop(); + InvalidateCompanyWindows(); cur_company.Restore(); }