From 525be22bd8d9375dbc7894fb2c6cda6526e2dce1 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Tue, 16 Feb 2021 12:52:33 -0800 Subject: [PATCH] Eliminate more transient allocations: Titles and invalid rectangles and bitmap runs and utf8 conversions (#8621) ## References * See also #8617 ## PR Checklist * [x] Supports #3075 * [x] I work here. * [x] Manual test. ## Detailed Description of the Pull Request / Additional comments ### Window Title Generation Every time the renderer checks the title, it's doing two bad things that I've fixed: 1. It's assembling the prefix to the full title doing a concatenation. No one ever gets just the prefix ever after it is set besides the concat. So instead of storing prefix and the title, I store the assembled prefix + title and the bare title. 2. A copy must be made because it was returning `std::wstring` instead of `std::wstring&`. Now it returns the ref. ### Dirty Area Return Every time the renderer checks the dirty area, which is sometimes multiple times per pass (regular text printing, again for selection, etc.), a vector is created off the heap to return the rectangles. The consumers only ever iterate this data. Now we return a span over a rectangle or rectangles that the engine must store itself. 1. For some renderers, it's always a constant 1 element. They update that 1 element when dirty is queried and return it in the span with a span size of 1. 2. For other renderers with more complex behavior, they're already holding a cached vector of rectangles. Now it's effectively giving out the ref to those in the span for iteration. ### Bitmap Runs The `til::bitmap` used a `std::optional>` inside itself to cache its runs and would clear the optional when the runs became invalidated. Unfortunately doing `.reset()` to clear the optional will destroy the underlying vector and have it release its memory. We know it's about to get reallocated again, so we're just going to make it a `std::pmr::vector` and give it a memory pool. The alternative solution here was to use a `bool` and `std::vector` and just flag when the vector was invalid, but that was honestly more code changes and I love excuses to try out PMR now. Also, instead of returning the ref to the vector... I'm just returning a span now. Everyone just iterates it anyway, may as well not share the implementation detail. ### UTF-8 conversions When testing with Terminal and looking at the `conhost.exe`'s PTY renderer, it spends a TON of allocation time on converting all the UTF-16 stuff inside to UTF-8 before it sends it out the PTY. This was because `ConvertToA` was allocating a string inside itself and returning it just to have it freed after printing and looping back around again... as a PTY does. The change here is to use `til::u16u8` that accepts a buffer out parameter so the caller can just hold onto it. ## Validation Steps Performed - [x] `big.txt` in conhost.exe (GDI renderer) - [x] `big.txt` in Terminal (DX, PTY renderer) - [x] Ensure WDDM and BGFX build under Razzle with this change. --- src/cascadia/TerminalCore/Terminal.hpp | 2 +- .../TerminalCore/terminalrenderdata.cpp | 2 +- src/host/consoleInformation.cpp | 37 ++++++++++++------- src/host/getset.cpp | 20 ++-------- src/host/renderData.cpp | 2 +- src/host/renderData.hpp | 2 +- src/host/server.h | 17 +++++---- src/host/ut_host/ApiRoutinesTests.cpp | 37 ++++++++++++------- src/host/ut_host/VtIoTests.cpp | 4 +- src/inc/til/bitmap.h | 4 +- src/interactivity/onecore/BgfxEngine.cpp | 11 ++++-- src/interactivity/onecore/BgfxEngine.hpp | 5 ++- src/interactivity/win32/window.cpp | 8 +++- src/interactivity/win32/windowproc.cpp | 5 ++- src/renderer/base/RenderEngineBase.cpp | 4 +- src/renderer/base/renderer.cpp | 19 ++++++---- src/renderer/dx/DxRenderer.cpp | 16 +++++--- src/renderer/dx/DxRenderer.hpp | 7 ++-- src/renderer/gdi/gdirenderer.hpp | 5 ++- src/renderer/gdi/math.cpp | 16 +++++--- src/renderer/gdi/state.cpp | 3 +- src/renderer/inc/IRenderData.hpp | 2 +- src/renderer/inc/IRenderEngine.hpp | 6 +-- src/renderer/inc/RenderEngineBase.hpp | 6 +-- src/renderer/uia/UiaRenderer.cpp | 14 ++++--- src/renderer/uia/UiaRenderer.hpp | 4 +- src/renderer/vt/XtermEngine.cpp | 5 ++- src/renderer/vt/XtermEngine.hpp | 2 +- src/renderer/vt/math.cpp | 11 +++--- src/renderer/vt/paint.cpp | 2 +- src/renderer/vt/state.cpp | 16 ++++---- src/renderer/vt/tracing.cpp | 2 +- src/renderer/vt/tracing.hpp | 2 +- src/renderer/vt/vtrenderer.hpp | 8 ++-- src/renderer/wddmcon/WddmConRenderer.cpp | 11 ++++-- src/renderer/wddmcon/WddmConRenderer.hpp | 5 ++- 36 files changed, 187 insertions(+), 135 deletions(-) diff --git a/src/cascadia/TerminalCore/Terminal.hpp b/src/cascadia/TerminalCore/Terminal.hpp index dcd64d71c..7def2cf72 100644 --- a/src/cascadia/TerminalCore/Terminal.hpp +++ b/src/cascadia/TerminalCore/Terminal.hpp @@ -182,7 +182,7 @@ public: void SelectNewRegion(const COORD coordStart, const COORD coordEnd) override; const COORD GetSelectionAnchor() const noexcept override; const COORD GetSelectionEnd() const noexcept override; - const std::wstring GetConsoleTitle() const noexcept override; + const std::wstring_view GetConsoleTitle() const noexcept override; void ColorSelection(const COORD coordSelectionStart, const COORD coordSelectionEnd, const TextAttribute) override; #pragma endregion diff --git a/src/cascadia/TerminalCore/terminalrenderdata.cpp b/src/cascadia/TerminalCore/terminalrenderdata.cpp index 212f7c768..17b711db7 100644 --- a/src/cascadia/TerminalCore/terminalrenderdata.cpp +++ b/src/cascadia/TerminalCore/terminalrenderdata.cpp @@ -215,7 +215,7 @@ void Terminal::SelectNewRegion(const COORD coordStart, const COORD coordEnd) SetSelectionEnd(realCoordEnd, SelectionExpansionMode::Cell); } -const std::wstring Terminal::GetConsoleTitle() const noexcept +const std::wstring_view Terminal::GetConsoleTitle() const noexcept try { if (_title.has_value()) diff --git a/src/host/consoleInformation.cpp b/src/host/consoleInformation.cpp index 60ad4ff42..81ef9faa7 100644 --- a/src/host/consoleInformation.cpp +++ b/src/host/consoleInformation.cpp @@ -24,6 +24,8 @@ CONSOLE_INFORMATION::CONSOLE_INFORMATION() : // ExeAliasList initialized below _OriginalTitle(), _Title(), + _Prefix(), + _TitleAndPrefix(), _LinkTitle(), Flags(0), PopupCount(0), @@ -115,7 +117,12 @@ ULONG CONSOLE_INFORMATION::GetCSRecursionCount() try { gci.SetTitle(title); - gci.SetOriginalTitle(std::wstring(TranslateConsoleTitle(gci.GetTitle().c_str(), TRUE, FALSE))); + + // TranslateConsoleTitle must have a null terminated string. + // This should only happen once on startup so the copy shouldn't be costly + // but could be eliminated by rewriting TranslateConsoleTitle. + const std::wstring nullTerminatedTitle{ gci.GetTitle() }; + gci.SetOriginalTitle(std::wstring(TranslateConsoleTitle(nullTerminatedTitle.c_str(), TRUE, FALSE))); } catch (...) { @@ -269,6 +276,7 @@ std::pair CONSOLE_INFORMATION::LookupAttributeColors(const T void CONSOLE_INFORMATION::SetTitle(const std::wstring_view newTitle) { _Title = std::wstring{ newTitle.begin(), newTitle.end() }; + _TitleAndPrefix = _Prefix + _Title; auto* const pRender = ServiceLocator::LocateGlobals().pRender; if (pRender) @@ -284,9 +292,10 @@ void CONSOLE_INFORMATION::SetTitle(const std::wstring_view newTitle) // - newTitlePrefix: The new value to use for the title prefix // Return Value: // - -void CONSOLE_INFORMATION::SetTitlePrefix(const std::wstring& newTitlePrefix) +void CONSOLE_INFORMATION::SetTitlePrefix(const std::wstring_view newTitlePrefix) { - _TitlePrefix = newTitlePrefix; + _Prefix = newTitlePrefix; + _TitleAndPrefix = _Prefix + _Title; auto* const pRender = ServiceLocator::LocateGlobals().pRender; if (pRender) @@ -302,7 +311,7 @@ void CONSOLE_INFORMATION::SetTitlePrefix(const std::wstring& newTitlePrefix) // - originalTitle: The new value to use for the console's original title // Return Value: // - -void CONSOLE_INFORMATION::SetOriginalTitle(const std::wstring& originalTitle) +void CONSOLE_INFORMATION::SetOriginalTitle(const std::wstring_view originalTitle) { _OriginalTitle = originalTitle; } @@ -314,7 +323,7 @@ void CONSOLE_INFORMATION::SetOriginalTitle(const std::wstring& originalTitle) // - linkTitle: The new value to use for the console's link title // Return Value: // - -void CONSOLE_INFORMATION::SetLinkTitle(const std::wstring& linkTitle) +void CONSOLE_INFORMATION::SetLinkTitle(const std::wstring_view linkTitle) { _LinkTitle = linkTitle; } @@ -324,8 +333,8 @@ void CONSOLE_INFORMATION::SetLinkTitle(const std::wstring& linkTitle) // Arguments: // - // Return Value: -// - a reference to the console's title. -const std::wstring& CONSOLE_INFORMATION::GetTitle() const noexcept +// - the console's title. +const std::wstring_view CONSOLE_INFORMATION::GetTitle() const noexcept { return _Title; } @@ -336,10 +345,10 @@ const std::wstring& CONSOLE_INFORMATION::GetTitle() const noexcept // Arguments: // - // Return Value: -// - a new wstring containing the combined prefix and title. -const std::wstring CONSOLE_INFORMATION::GetTitleAndPrefix() const +// - the combined prefix and title. +const std::wstring_view CONSOLE_INFORMATION::GetTitleAndPrefix() const { - return _TitlePrefix + _Title; + return _TitleAndPrefix; } // Method Description: @@ -347,8 +356,8 @@ const std::wstring CONSOLE_INFORMATION::GetTitleAndPrefix() const // Arguments: // - // Return Value: -// - a reference to the console's original title. -const std::wstring& CONSOLE_INFORMATION::GetOriginalTitle() const noexcept +// - the console's original title. +const std::wstring_view CONSOLE_INFORMATION::GetOriginalTitle() const noexcept { return _OriginalTitle; } @@ -358,8 +367,8 @@ const std::wstring& CONSOLE_INFORMATION::GetOriginalTitle() const noexcept // Arguments: // - // Return Value: -// - a reference to the console's link title. -const std::wstring& CONSOLE_INFORMATION::GetLinkTitle() const noexcept +// - the console's link title. +const std::wstring_view CONSOLE_INFORMATION::GetLinkTitle() const noexcept { return _LinkTitle; } diff --git a/src/host/getset.cpp b/src/host/getset.cpp index e380f442c..b3ccb9ef7 100644 --- a/src/host/getset.cpp +++ b/src/host/getset.cpp @@ -1660,33 +1660,21 @@ void DoSrvPrivateRefreshWindow(_In_ const SCREEN_INFORMATION& screenInfo) } // Get the appropriate title and length depending on the mode. - const wchar_t* pwszTitle; - size_t cchTitleLength; - - if (isOriginal) - { - pwszTitle = gci.GetOriginalTitle().c_str(); - cchTitleLength = gci.GetOriginalTitle().length(); - } - else - { - pwszTitle = gci.GetTitle().c_str(); - cchTitleLength = gci.GetTitle().length(); - } + const std::wstring_view storedTitle = isOriginal ? gci.GetOriginalTitle() : gci.GetTitle(); // Always report how much space we would need. - needed = cchTitleLength; + needed = storedTitle.size(); // If we have a pointer to receive the data, then copy it out. if (title.has_value()) { - HRESULT const hr = StringCchCopyNW(title->data(), title->size(), pwszTitle, cchTitleLength); + HRESULT const hr = StringCchCopyNW(title->data(), title->size(), storedTitle.data(), storedTitle.size()); // Insufficient buffer is allowed. If we return a partial string, that's still OK by historical/compat standards. // Just say how much we managed to return. if (SUCCEEDED(hr) || STRSAFE_E_INSUFFICIENT_BUFFER == hr) { - written = std::min(title->size(), cchTitleLength); + written = std::min(title->size(), storedTitle.size()); } } return S_OK; diff --git a/src/host/renderData.cpp b/src/host/renderData.cpp index a77758930..c860b3da3 100644 --- a/src/host/renderData.cpp +++ b/src/host/renderData.cpp @@ -318,7 +318,7 @@ const bool RenderData::IsGridLineDrawingAllowed() noexcept // - Retrieves the title information to be displayed in the frame/edge of the window // Return Value: // - String with title information -const std::wstring RenderData::GetConsoleTitle() const noexcept +const std::wstring_view RenderData::GetConsoleTitle() const noexcept { const CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); return gci.GetTitleAndPrefix(); diff --git a/src/host/renderData.hpp b/src/host/renderData.hpp index 78367bdbf..9e1e79b0b 100644 --- a/src/host/renderData.hpp +++ b/src/host/renderData.hpp @@ -54,7 +54,7 @@ public: const bool IsGridLineDrawingAllowed() noexcept override; - const std::wstring GetConsoleTitle() const noexcept override; + const std::wstring_view GetConsoleTitle() const noexcept override; const std::wstring GetHyperlinkUri(uint16_t id) const noexcept override; const std::wstring GetHyperlinkCustomId(uint16_t id) const noexcept override; diff --git a/src/host/server.h b/src/host/server.h index da408a4f4..91ea54537 100644 --- a/src/host/server.h +++ b/src/host/server.h @@ -129,13 +129,13 @@ public: std::pair LookupAttributeColors(const TextAttribute& attr) const noexcept; void SetTitle(const std::wstring_view newTitle); - void SetTitlePrefix(const std::wstring& newTitlePrefix); - void SetOriginalTitle(const std::wstring& originalTitle); - void SetLinkTitle(const std::wstring& linkTitle); - const std::wstring& GetTitle() const noexcept; - const std::wstring& GetOriginalTitle() const noexcept; - const std::wstring& GetLinkTitle() const noexcept; - const std::wstring GetTitleAndPrefix() const; + void SetTitlePrefix(const std::wstring_view newTitlePrefix); + void SetOriginalTitle(const std::wstring_view originalTitle); + void SetLinkTitle(const std::wstring_view linkTitle); + const std::wstring_view GetTitle() const noexcept; + const std::wstring_view GetOriginalTitle() const noexcept; + const std::wstring_view GetLinkTitle() const noexcept; + const std::wstring_view GetTitleAndPrefix() const; [[nodiscard]] static NTSTATUS AllocateConsole(const std::wstring_view title); // MSFT:16886775 : get rid of friends @@ -152,7 +152,8 @@ public: private: CRITICAL_SECTION _csConsoleLock; // serialize input and output using this std::wstring _Title; - std::wstring _TitlePrefix; // Eg Select, Mark - things that we manually prepend to the title. + std::wstring _Prefix; // Eg Select, Mark - things that we manually prepend to the title. + std::wstring _TitleAndPrefix; std::wstring _OriginalTitle; std::wstring _LinkTitle; // Path to .lnk file SCREEN_INFORMATION* pCurrentScreenBuffer; diff --git a/src/host/ut_host/ApiRoutinesTests.cpp b/src/host/ut_host/ApiRoutinesTests.cpp index 4ce5a6ac0..bf0f7ed36 100644 --- a/src/host/ut_host/ApiRoutinesTests.cpp +++ b/src/host/ut_host/ApiRoutinesTests.cpp @@ -207,10 +207,12 @@ class ApiRoutinesTests CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); gci.SetTitle(L"Test window title."); + const auto title = gci.GetTitle(); + int const iBytesNeeded = WideCharToMultiByte(gci.OutputCP, 0, - gci.GetTitle().c_str(), - -1, + title.data(), + gsl::narrow_cast(title.size()), nullptr, 0, nullptr, @@ -221,8 +223,8 @@ class ApiRoutinesTests VERIFY_WIN32_BOOL_SUCCEEDED(WideCharToMultiByte(gci.OutputCP, 0, - gci.GetTitle().c_str(), - -1, + title.data(), + gsl::narrow_cast(title.size()), pszExpected.get(), iBytesNeeded, nullptr, @@ -251,10 +253,13 @@ class ApiRoutinesTests VERIFY_SUCCEEDED(_pApiRoutines->GetConsoleTitleWImpl(gsl::span(pwszTitle, ARRAYSIZE(pwszTitle)), cchWritten, cchNeeded)); VERIFY_ARE_NOT_EQUAL(0u, cchWritten); + + const auto title = gci.GetTitle(); + // NOTE: W version of API returns string length. A version of API returns buffer length (string + null). - VERIFY_ARE_EQUAL(gci.GetTitle().length(), cchWritten); - VERIFY_ARE_EQUAL(gci.GetTitle().length(), cchNeeded); - VERIFY_ARE_EQUAL(WEX::Common::String(gci.GetTitle().c_str()), WEX::Common::String(pwszTitle)); + VERIFY_ARE_EQUAL(title.length(), cchWritten); + VERIFY_ARE_EQUAL(title.length(), cchNeeded); + VERIFY_ARE_EQUAL(WEX::Common::String(title.data(), gsl::narrow_cast(title.size())), WEX::Common::String(pwszTitle)); } TEST_METHOD(ApiGetConsoleOriginalTitleA) @@ -262,10 +267,12 @@ class ApiRoutinesTests CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation(); gci.SetOriginalTitle(L"Test original window title."); + const auto originalTitle = gci.GetOriginalTitle(); + int const iBytesNeeded = WideCharToMultiByte(gci.OutputCP, 0, - gci.GetOriginalTitle().c_str(), - -1, + originalTitle.data(), + gsl::narrow_cast(originalTitle.size()), nullptr, 0, nullptr, @@ -276,8 +283,8 @@ class ApiRoutinesTests VERIFY_WIN32_BOOL_SUCCEEDED(WideCharToMultiByte(gci.OutputCP, 0, - gci.GetOriginalTitle().c_str(), - -1, + originalTitle.data(), + gsl::narrow_cast(originalTitle.size()), pszExpected.get(), iBytesNeeded, nullptr, @@ -306,10 +313,12 @@ class ApiRoutinesTests VERIFY_SUCCEEDED(_pApiRoutines->GetConsoleOriginalTitleWImpl(gsl::span(pwszTitle, ARRAYSIZE(pwszTitle)), cchWritten, cchNeeded)); VERIFY_ARE_NOT_EQUAL(0u, cchWritten); + + const auto originalTitle = gci.GetOriginalTitle(); // NOTE: W version of API returns string length. A version of API returns buffer length (string + null). - VERIFY_ARE_EQUAL(gci.GetOriginalTitle().length(), cchWritten); - VERIFY_ARE_EQUAL(gci.GetOriginalTitle().length(), cchNeeded); - VERIFY_ARE_EQUAL(WEX::Common::String(gci.GetOriginalTitle().c_str()), WEX::Common::String(pwszTitle)); + VERIFY_ARE_EQUAL(originalTitle.length(), cchWritten); + VERIFY_ARE_EQUAL(originalTitle.length(), cchNeeded); + VERIFY_ARE_EQUAL(WEX::Common::String(originalTitle.data(), gsl::narrow_cast(originalTitle.size())), WEX::Common::String(pwszTitle)); } static void s_AdjustOutputWait(const bool fShouldBlock) diff --git a/src/host/ut_host/VtIoTests.cpp b/src/host/ut_host/VtIoTests.cpp index 314fea273..6497cb6bc 100644 --- a/src/host/ut_host/VtIoTests.cpp +++ b/src/host/ut_host/VtIoTests.cpp @@ -355,9 +355,9 @@ public: return false; } - const std::wstring GetConsoleTitle() const noexcept override + const std::wstring_view GetConsoleTitle() const noexcept override { - return std::wstring{}; + return std::wstring_view{}; } const bool IsSelectionActive() const override diff --git a/src/inc/til/bitmap.h b/src/inc/til/bitmap.h index eff5f1f64..f4bef68b6 100644 --- a/src/inc/til/bitmap.h +++ b/src/inc/til/bitmap.h @@ -263,7 +263,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned" return const_iterator(_bits, _sz, _sz.area()); } - const std::vector& runs() const + const gsl::span runs() const { // If we don't have cached runs, rebuild. if (!_runs.has_value()) @@ -271,7 +271,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned" _runs.emplace(begin(), end()); } - // Return a reference to the runs. + // Return the runs. return _runs.value(); } diff --git a/src/interactivity/onecore/BgfxEngine.cpp b/src/interactivity/onecore/BgfxEngine.cpp index 74fe40c42..9a8d03fde 100644 --- a/src/interactivity/onecore/BgfxEngine.cpp +++ b/src/interactivity/onecore/BgfxEngine.cpp @@ -230,7 +230,7 @@ BgfxEngine::BgfxEngine(PVOID SharedViewBase, LONG DisplayHeight, LONG DisplayWid return S_OK; } -std::vector BgfxEngine::GetDirtyArea() +[[nodiscard]] HRESULT BgfxEngine::GetDirtyArea(gsl::span& area) noexcept { SMALL_RECT r; r.Bottom = _displayHeight > 0 ? (SHORT)(_displayHeight - 1) : 0; @@ -238,7 +238,12 @@ std::vector BgfxEngine::GetDirtyArea() r.Left = 0; r.Right = _displayWidth > 0 ? (SHORT)(_displayWidth - 1) : 0; - return { r }; + _dirtyArea = r; + + area = { &_dirtyArea, + 1 }; + + return S_OK; } [[nodiscard]] HRESULT BgfxEngine::GetFontSize(_Out_ COORD* const pFontSize) noexcept @@ -260,7 +265,7 @@ std::vector BgfxEngine::GetDirtyArea() // - newTitle: the new string to use for the title of the window // Return Value: // - S_OK -[[nodiscard]] HRESULT BgfxEngine::_DoUpdateTitle(_In_ const std::wstring& /*newTitle*/) noexcept +[[nodiscard]] HRESULT BgfxEngine::_DoUpdateTitle(_In_ const std::wstring_view /*newTitle*/) noexcept { return S_OK; } diff --git a/src/interactivity/onecore/BgfxEngine.hpp b/src/interactivity/onecore/BgfxEngine.hpp index 282fdd1ec..542daa6e5 100644 --- a/src/interactivity/onecore/BgfxEngine.hpp +++ b/src/interactivity/onecore/BgfxEngine.hpp @@ -67,12 +67,12 @@ namespace Microsoft::Console::Render [[nodiscard]] HRESULT GetProposedFont(const FontInfoDesired& fiFontInfoDesired, FontInfo& fiFontInfo, int const iDpi) noexcept override; - std::vector GetDirtyArea() override; + [[nodiscard]] HRESULT GetDirtyArea(gsl::span& area) noexcept override; [[nodiscard]] HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept override; [[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept override; protected: - [[nodiscard]] HRESULT _DoUpdateTitle(_In_ const std::wstring& newTitle) noexcept override; + [[nodiscard]] HRESULT _DoUpdateTitle(_In_ const std::wstring_view newTitle) noexcept override; private: ULONG_PTR _sharedViewBase; @@ -80,6 +80,7 @@ namespace Microsoft::Console::Render LONG _displayHeight; LONG _displayWidth; + til::rectangle _dirtyArea; COORD _fontSize; diff --git a/src/interactivity/win32/window.cpp b/src/interactivity/win32/window.cpp index e7a7c774d..e42a4e074 100644 --- a/src/interactivity/win32/window.cpp +++ b/src/interactivity/win32/window.cpp @@ -289,11 +289,17 @@ void Window::_UpdateSystemMetrics() const } } + // CreateWindowExW needs a null terminated string, so ensure + // title is null terminated in a std::wstring here. + // We don't mind the string copy here because making the window + // should be infrequent. + const std::wstring title{ gci.GetTitle() }; + // Attempt to create window HWND hWnd = CreateWindowExW( CONSOLE_WINDOW_EX_FLAGS, CONSOLE_WINDOW_CLASS, - gci.GetTitle().c_str(), + title.c_str(), CONSOLE_WINDOW_FLAGS, WI_IsFlagSet(gci.Flags, CONSOLE_AUTO_POSITION) ? CW_USEDEFAULT : rectProposed.left, rectProposed.top, // field is ignored if CW_USEDEFAULT was chosen above diff --git a/src/interactivity/win32/windowproc.cpp b/src/interactivity/win32/windowproc.cpp index c9075d4c2..8a14be8a5 100644 --- a/src/interactivity/win32/windowproc.cpp +++ b/src/interactivity/win32/windowproc.cpp @@ -687,7 +687,10 @@ using namespace Microsoft::Console::Types; case CM_UPDATE_TITLE: { - SetWindowTextW(hWnd, gci.GetTitleAndPrefix().c_str()); + // SetWindowTextW needs null terminated string so assign view to string. + const std::wstring titleAndPrefix{ gci.GetTitleAndPrefix() }; + + SetWindowTextW(hWnd, titleAndPrefix.c_str()); break; } diff --git a/src/renderer/base/RenderEngineBase.cpp b/src/renderer/base/RenderEngineBase.cpp index 1d0571d29..9830e4871 100644 --- a/src/renderer/base/RenderEngineBase.cpp +++ b/src/renderer/base/RenderEngineBase.cpp @@ -13,7 +13,7 @@ RenderEngineBase::RenderEngineBase() : { } -HRESULT RenderEngineBase::InvalidateTitle(const std::wstring& proposedTitle) noexcept +HRESULT RenderEngineBase::InvalidateTitle(const std::wstring_view proposedTitle) noexcept { if (proposedTitle != _lastFrameTitle) { @@ -23,7 +23,7 @@ HRESULT RenderEngineBase::InvalidateTitle(const std::wstring& proposedTitle) noe return S_OK; } -HRESULT RenderEngineBase::UpdateTitle(const std::wstring& newTitle) noexcept +HRESULT RenderEngineBase::UpdateTitle(const std::wstring_view newTitle) noexcept { HRESULT hr = S_FALSE; if (newTitle != _lastFrameTitle) diff --git a/src/renderer/base/renderer.cpp b/src/renderer/base/renderer.cpp index 09df6184e..31a9d2f69 100644 --- a/src/renderer/base/renderer.cpp +++ b/src/renderer/base/renderer.cpp @@ -467,7 +467,7 @@ void Renderer::TriggerCircling() // - void Renderer::TriggerTitleChange() { - const std::wstring newTitle = _pData->GetConsoleTitle(); + const auto newTitle = _pData->GetConsoleTitle(); for (IRenderEngine* const pEngine : _rgpEngines) { LOG_IF_FAILED(pEngine->InvalidateTitle(newTitle)); @@ -483,7 +483,7 @@ void Renderer::TriggerTitleChange() // - the HRESULT of the underlying engine's UpdateTitle call. HRESULT Renderer::_PaintTitle(IRenderEngine* const pEngine) { - const std::wstring newTitle = _pData->GetConsoleTitle(); + const auto newTitle = _pData->GetConsoleTitle(); return pEngine->UpdateTitle(newTitle); } @@ -627,9 +627,10 @@ void Renderer::_PaintBufferOutput(_In_ IRenderEngine* const pEngine) // This is effectively the number of cells on the visible screen that need to be redrawn. // The origin is always 0, 0 because it represents the screen itself, not the underlying buffer. - const auto dirtyAreas = pEngine->GetDirtyArea(); + gsl::span dirtyAreas; + LOG_IF_FAILED(pEngine->GetDirtyArea(dirtyAreas)); - for (const auto dirtyRect : dirtyAreas) + for (const auto& dirtyRect : dirtyAreas) { auto dirty = Viewport::FromInclusive(dirtyRect); @@ -1044,7 +1045,10 @@ void Renderer::_PaintOverlay(IRenderEngine& engine, // Set it up in a Viewport helper structure and trim it the IME viewport to be within the full console viewport. Viewport viewConv = Viewport::FromInclusive(srCaView); - for (SMALL_RECT srDirty : engine.GetDirtyArea()) + gsl::span dirtyAreas; + LOG_IF_FAILED(engine.GetDirtyArea(dirtyAreas)); + + for (SMALL_RECT srDirty : dirtyAreas) { // Dirty is an inclusive rectangle, but oddly enough the IME was an exclusive one, so correct it. srDirty.Bottom++; @@ -1101,13 +1105,14 @@ void Renderer::_PaintSelection(_In_ IRenderEngine* const pEngine) { try { - auto dirtyAreas = pEngine->GetDirtyArea(); + gsl::span dirtyAreas; + LOG_IF_FAILED(pEngine->GetDirtyArea(dirtyAreas)); // Get selection rectangles const auto rectangles = _GetSelectionRects(); for (auto rect : rectangles) { - for (auto dirtyRect : dirtyAreas) + for (auto& dirtyRect : dirtyAreas) { // Make a copy as `TrimToViewport` will manipulate it and // can destroy it for the next dirtyRect to test against. diff --git a/src/renderer/dx/DxRenderer.cpp b/src/renderer/dx/DxRenderer.cpp index 5c5709a0d..a66d312e9 100644 --- a/src/renderer/dx/DxRenderer.cpp +++ b/src/renderer/dx/DxRenderer.cpp @@ -66,7 +66,8 @@ using namespace Microsoft::Console::Types; DxEngine::DxEngine() : RenderEngineBase(), _invalidateFullRows{ true }, - _invalidMap{}, + _pool{ til::pmr::get_default_resource() }, + _invalidMap{ &_pool }, _invalidScroll{}, _allInvalid{ false }, _firstFrame{ true }, @@ -2087,13 +2088,16 @@ float DxEngine::GetScaling() const noexcept // Routine Description: // - Gets the area that we currently believe is dirty within the character cell grid // Arguments: -// - +// - area - Rectangle describing dirty area in characters. // Return Value: -// - Rectangle describing dirty area in characters. -[[nodiscard]] std::vector DxEngine::GetDirtyArea() +// - S_OK +[[nodiscard]] HRESULT DxEngine::GetDirtyArea(gsl::span& area) noexcept +try { - return _invalidMap.runs(); + area = _invalidMap.runs(); + return S_OK; } +CATCH_RETURN(); // Routine Description: // - Gets the current font size @@ -2141,7 +2145,7 @@ CATCH_RETURN(); // - newTitle: the new string to use for the title of the window // Return Value: // - S_OK -[[nodiscard]] HRESULT DxEngine::_DoUpdateTitle(_In_ const std::wstring& /*newTitle*/) noexcept +[[nodiscard]] HRESULT DxEngine::_DoUpdateTitle(_In_ const std::wstring_view /*newTitle*/) noexcept { if (_hwndTarget != INVALID_HANDLE_VALUE) { diff --git a/src/renderer/dx/DxRenderer.hpp b/src/renderer/dx/DxRenderer.hpp index 5d07702d8..344dedec3 100644 --- a/src/renderer/dx/DxRenderer.hpp +++ b/src/renderer/dx/DxRenderer.hpp @@ -113,7 +113,7 @@ namespace Microsoft::Console::Render [[nodiscard]] HRESULT GetProposedFont(const FontInfoDesired& fiFontInfoDesired, FontInfo& fiFontInfo, int const iDpi) noexcept override; - [[nodiscard]] std::vector GetDirtyArea() override; + [[nodiscard]] HRESULT GetDirtyArea(gsl::span& area) noexcept override; [[nodiscard]] HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept override; [[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept override; @@ -130,7 +130,7 @@ namespace Microsoft::Console::Render void UpdateHyperlinkHoveredId(const uint16_t hoveredId) noexcept; protected: - [[nodiscard]] HRESULT _DoUpdateTitle(_In_ const std::wstring& newTitle) noexcept override; + [[nodiscard]] HRESULT _DoUpdateTitle(_In_ const std::wstring_view newTitle) noexcept override; [[nodiscard]] HRESULT _PaintTerminalEffects() noexcept; [[nodiscard]] bool _FullRepaintNeeded() const noexcept; @@ -181,7 +181,8 @@ namespace Microsoft::Console::Render bool _firstFrame; bool _invalidateFullRows; - til::bitmap _invalidMap; + std::pmr::unsynchronized_pool_resource _pool; + til::pmr::bitmap _invalidMap; til::point _invalidScroll; bool _allInvalid; diff --git a/src/renderer/gdi/gdirenderer.hpp b/src/renderer/gdi/gdirenderer.hpp index 3be272c18..3038675ef 100644 --- a/src/renderer/gdi/gdirenderer.hpp +++ b/src/renderer/gdi/gdirenderer.hpp @@ -66,12 +66,12 @@ namespace Microsoft::Console::Render _Out_ FontInfo& Font, const int iDpi) noexcept override; - [[nodiscard]] std::vector GetDirtyArea() override; + [[nodiscard]] HRESULT GetDirtyArea(gsl::span& area) noexcept override; [[nodiscard]] HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept override; [[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept override; protected: - [[nodiscard]] HRESULT _DoUpdateTitle(_In_ const std::wstring& newTitle) noexcept override; + [[nodiscard]] HRESULT _DoUpdateTitle(_In_ const std::wstring_view newTitle) noexcept override; private: HWND _hwndTargetWindow; @@ -82,6 +82,7 @@ namespace Microsoft::Console::Render bool _fPaintStarted; + til::rectangle _invalidCharacters; PAINTSTRUCT _psInvalidData; HDC _hdcMemoryContext; bool _isTrueTypeFont; diff --git a/src/renderer/gdi/math.cpp b/src/renderer/gdi/math.cpp index 2dfecd049..a127021ef 100644 --- a/src/renderer/gdi/math.cpp +++ b/src/renderer/gdi/math.cpp @@ -12,18 +12,22 @@ using namespace Microsoft::Console::Render; // Routine Description: // - Gets the size in characters of the current dirty portion of the frame. // Arguments: -// - -// Return Value: -// - The character dimensions of the current dirty area of the frame. +// - area - The character dimensions of the current dirty area of the frame. // This is an Inclusive rect. -std::vector GdiEngine::GetDirtyArea() +// Return Value: +// - S_OK or math failure +[[nodiscard]] HRESULT GdiEngine::GetDirtyArea(gsl::span& area) noexcept { RECT rc = _psInvalidData.rcPaint; SMALL_RECT sr = { 0 }; - LOG_IF_FAILED(_ScaleByFont(&rc, &sr)); + RETURN_IF_FAILED(_ScaleByFont(&rc, &sr)); - return { sr }; + _invalidCharacters = sr; + + area = { &_invalidCharacters, 1 }; + + return S_OK; } // Routine Description: diff --git a/src/renderer/gdi/state.cpp b/src/renderer/gdi/state.cpp index d6030b597..81fba42d6 100644 --- a/src/renderer/gdi/state.cpp +++ b/src/renderer/gdi/state.cpp @@ -31,6 +31,7 @@ GdiEngine::GdiEngine() : _lastBg(INVALID_COLOR), _lastFontItalic(false), _fPaintStarted(false), + _invalidCharacters{}, _hfont(nullptr), _hfontItalic(nullptr), _pool{ til::pmr::get_default_resource() }, // It's important the pool is first so it can be given to the others on construction. @@ -392,7 +393,7 @@ GdiEngine::~GdiEngine() // - newTitle: the new string to use for the title of the window // Return Value: // - S_OK if PostMessageW succeeded, otherwise E_FAIL -[[nodiscard]] HRESULT GdiEngine::_DoUpdateTitle(_In_ const std::wstring& /*newTitle*/) noexcept +[[nodiscard]] HRESULT GdiEngine::_DoUpdateTitle(_In_ const std::wstring_view /*newTitle*/) noexcept { // the CM_UPDATE_TITLE handler in windowproc will query the updated title. return PostMessageW(_hwndTargetWindow, CM_UPDATE_TITLE, 0, (LPARAM) nullptr) ? S_OK : E_FAIL; diff --git a/src/renderer/inc/IRenderData.hpp b/src/renderer/inc/IRenderData.hpp index 47da94b8d..56ab872e2 100644 --- a/src/renderer/inc/IRenderData.hpp +++ b/src/renderer/inc/IRenderData.hpp @@ -64,7 +64,7 @@ namespace Microsoft::Console::Render virtual const std::vector GetOverlays() const noexcept = 0; virtual const bool IsGridLineDrawingAllowed() noexcept = 0; - virtual const std::wstring GetConsoleTitle() const noexcept = 0; + virtual const std::wstring_view GetConsoleTitle() const noexcept = 0; virtual const std::wstring GetHyperlinkUri(uint16_t id) const noexcept = 0; virtual const std::wstring GetHyperlinkCustomId(uint16_t id) const noexcept = 0; diff --git a/src/renderer/inc/IRenderEngine.hpp b/src/renderer/inc/IRenderEngine.hpp index 0894bb525..688df2f79 100644 --- a/src/renderer/inc/IRenderEngine.hpp +++ b/src/renderer/inc/IRenderEngine.hpp @@ -71,7 +71,7 @@ namespace Microsoft::Console::Render [[nodiscard]] virtual HRESULT InvalidateAll() noexcept = 0; [[nodiscard]] virtual HRESULT InvalidateCircling(_Out_ bool* const pForcePaint) noexcept = 0; - [[nodiscard]] virtual HRESULT InvalidateTitle(const std::wstring& proposedTitle) noexcept = 0; + [[nodiscard]] virtual HRESULT InvalidateTitle(const std::wstring_view proposedTitle) noexcept = 0; [[nodiscard]] virtual HRESULT PrepareRenderInfo(const RenderFrameInfo& info) noexcept = 0; @@ -100,10 +100,10 @@ namespace Microsoft::Console::Render _Out_ FontInfo& FontInfo, const int iDpi) noexcept = 0; - virtual std::vector GetDirtyArea() = 0; + [[nodiscard]] virtual HRESULT GetDirtyArea(gsl::span& area) noexcept = 0; [[nodiscard]] virtual HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept = 0; [[nodiscard]] virtual HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept = 0; - [[nodiscard]] virtual HRESULT UpdateTitle(const std::wstring& newTitle) noexcept = 0; + [[nodiscard]] virtual HRESULT UpdateTitle(const std::wstring_view newTitle) noexcept = 0; }; inline Microsoft::Console::Render::IRenderEngine::~IRenderEngine() {} diff --git a/src/renderer/inc/RenderEngineBase.hpp b/src/renderer/inc/RenderEngineBase.hpp index 81b2d7130..378a6a56d 100644 --- a/src/renderer/inc/RenderEngineBase.hpp +++ b/src/renderer/inc/RenderEngineBase.hpp @@ -34,9 +34,9 @@ namespace Microsoft::Console::Render RenderEngineBase& operator=(RenderEngineBase&&) = default; public: - [[nodiscard]] HRESULT InvalidateTitle(const std::wstring& proposedTitle) noexcept override; + [[nodiscard]] HRESULT InvalidateTitle(const std::wstring_view proposedTitle) noexcept override; - [[nodiscard]] HRESULT UpdateTitle(const std::wstring& newTitle) noexcept override; + [[nodiscard]] HRESULT UpdateTitle(const std::wstring_view newTitle) noexcept override; [[nodiscard]] HRESULT PrepareRenderInfo(const RenderFrameInfo& info) noexcept override; @@ -45,7 +45,7 @@ namespace Microsoft::Console::Render void WaitUntilCanRender() noexcept override; protected: - [[nodiscard]] virtual HRESULT _DoUpdateTitle(const std::wstring& newTitle) noexcept = 0; + [[nodiscard]] virtual HRESULT _DoUpdateTitle(const std::wstring_view newTitle) noexcept = 0; bool _titleChanged; std::wstring _lastFrameTitle; diff --git a/src/renderer/uia/UiaRenderer.cpp b/src/renderer/uia/UiaRenderer.cpp index 124fb5307..f3a848fa7 100644 --- a/src/renderer/uia/UiaRenderer.cpp +++ b/src/renderer/uia/UiaRenderer.cpp @@ -427,12 +427,16 @@ CATCH_RETURN(); // - Gets the area that we currently believe is dirty within the character cell grid // - Not currently used by UiaEngine. // Arguments: -// - +// - area - Rectangle describing dirty area in characters. // Return Value: -// - Rectangle describing dirty area in characters. -[[nodiscard]] std::vector UiaEngine::GetDirtyArea() +// - S_OK. +[[nodiscard]] HRESULT UiaEngine::GetDirtyArea(gsl::span& area) noexcept { - return { Viewport::Empty().ToInclusive() }; + // Magic static is only valid because any instance of this object has the same behavior. + // Use member variable instead if this ever changes. + const static til::rectangle empty; + area = { &empty, 1 }; + return S_OK; } // Routine Description: @@ -465,7 +469,7 @@ CATCH_RETURN(); // - newTitle: the new string to use for the title of the window // Return Value: // - S_FALSE -[[nodiscard]] HRESULT UiaEngine::_DoUpdateTitle(_In_ const std::wstring& /*newTitle*/) noexcept +[[nodiscard]] HRESULT UiaEngine::_DoUpdateTitle(_In_ const std::wstring_view /*newTitle*/) noexcept { return S_FALSE; } diff --git a/src/renderer/uia/UiaRenderer.hpp b/src/renderer/uia/UiaRenderer.hpp index 68c230850..23b092c6e 100644 --- a/src/renderer/uia/UiaRenderer.hpp +++ b/src/renderer/uia/UiaRenderer.hpp @@ -69,12 +69,12 @@ namespace Microsoft::Console::Render [[nodiscard]] HRESULT GetProposedFont(const FontInfoDesired& fiFontInfoDesired, FontInfo& fiFontInfo, int const iDpi) noexcept override; - [[nodiscard]] std::vector GetDirtyArea() override; + [[nodiscard]] HRESULT GetDirtyArea(gsl::span& area) noexcept override; [[nodiscard]] HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept override; [[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept override; protected: - [[nodiscard]] HRESULT _DoUpdateTitle(const std::wstring& newTitle) noexcept override; + [[nodiscard]] HRESULT _DoUpdateTitle(const std::wstring_view newTitle) noexcept override; private: bool _isEnabled; diff --git a/src/renderer/vt/XtermEngine.cpp b/src/renderer/vt/XtermEngine.cpp index 34101935a..a948acd82 100644 --- a/src/renderer/vt/XtermEngine.cpp +++ b/src/renderer/vt/XtermEngine.cpp @@ -57,7 +57,8 @@ XtermEngine::XtermEngine(_In_ wil::unique_hfile hPipe, } else { - const auto dirty = GetDirtyArea(); + gsl::span dirty; + RETURN_IF_FAILED(GetDirtyArea(dirty)); // If we have 0 or 1 dirty pieces in the area, set as appropriate. Viewport dirtyView = dirty.empty() ? Viewport::Empty() : Viewport::FromInclusive(til::at(dirty, 0)); @@ -540,7 +541,7 @@ CATCH_RETURN(); // - newTitle: the new string to use for the title of the window // Return Value: // - S_OK -[[nodiscard]] HRESULT XtermEngine::_DoUpdateTitle(const std::wstring& newTitle) noexcept +[[nodiscard]] HRESULT XtermEngine::_DoUpdateTitle(const std::wstring_view newTitle) noexcept { // inbox telnet uses xterm-ascii as its mode. If we're in ascii mode, don't // do anything, to maintain compatibility. diff --git a/src/renderer/vt/XtermEngine.hpp b/src/renderer/vt/XtermEngine.hpp index 9e4680fe6..1dcf2d173 100644 --- a/src/renderer/vt/XtermEngine.hpp +++ b/src/renderer/vt/XtermEngine.hpp @@ -59,7 +59,7 @@ namespace Microsoft::Console::Render [[nodiscard]] HRESULT _MoveCursor(const COORD coord) noexcept override; - [[nodiscard]] HRESULT _DoUpdateTitle(const std::wstring& newTitle) noexcept override; + [[nodiscard]] HRESULT _DoUpdateTitle(const std::wstring_view newTitle) noexcept override; #ifdef UNIT_TESTING friend class VtRendererTest; diff --git a/src/renderer/vt/math.cpp b/src/renderer/vt/math.cpp index cab0c5ec7..548343993 100644 --- a/src/renderer/vt/math.cpp +++ b/src/renderer/vt/math.cpp @@ -13,13 +13,14 @@ using namespace Microsoft::Console::Types; // Routine Description: // - Gets the size in characters of the current dirty portion of the frame. // Arguments: -// - +// - area - The character dimensions of the current dirty area of the frame. +// This is an Inclusive rect. // Return Value: -// - The character dimensions of the current dirty area of the frame. -// This is an Inclusive rect. -std::vector VtEngine::GetDirtyArea() +// - S_OK. +[[nodiscard]] HRESULT VtEngine::GetDirtyArea(gsl::span& area) noexcept { - return _invalidMap.runs(); + area = _invalidMap.runs(); + return S_OK; } // Routine Description: diff --git a/src/renderer/vt/paint.cpp b/src/renderer/vt/paint.cpp index 485adddd6..f8b8a1266 100644 --- a/src/renderer/vt/paint.cpp +++ b/src/renderer/vt/paint.cpp @@ -598,7 +598,7 @@ using namespace Microsoft::Console::Types; // - newTitle: the new string to use for the title of the window // Return Value: // - S_OK -[[nodiscard]] HRESULT VtEngine::_DoUpdateTitle(const std::wstring& /*newTitle*/) noexcept +[[nodiscard]] HRESULT VtEngine::_DoUpdateTitle(const std::wstring_view /*newTitle*/) noexcept { return S_OK; } diff --git a/src/renderer/vt/state.cpp b/src/renderer/vt/state.cpp index 05dab05e1..a324e988b 100644 --- a/src/renderer/vt/state.cpp +++ b/src/renderer/vt/state.cpp @@ -31,7 +31,8 @@ VtEngine::VtEngine(_In_ wil::unique_hfile pipe, _hFile(std::move(pipe)), _lastTextAttributes(INVALID_COLOR, INVALID_COLOR), _lastViewport(initialViewport), - _invalidMap(initialViewport.Dimensions()), + _pool(til::pmr::get_default_resource()), + _invalidMap(initialViewport.Dimensions(), false, &_pool), _lastText({ 0 }), _scrollDelta({ 0, 0 }), _quickReturn(false), @@ -50,7 +51,10 @@ VtEngine::VtEngine(_In_ wil::unique_hfile pipe, _deferredCursorPos{ INVALID_COORDS }, _inResizeRequest{ false }, _trace{}, - _bufferLine{} + _bufferLine{}, + _buffer{}, + _formatBuffer{}, + _conversionBuffer{} { #ifndef UNIT_TESTING // When unit testing, we can instantiate a VtEngine without a pipe. @@ -144,12 +148,8 @@ VtEngine::VtEngine(_In_ wil::unique_hfile pipe, // - S_OK or suitable HRESULT error from either conversion or writing pipe. [[nodiscard]] HRESULT VtEngine::_WriteTerminalUtf8(const std::wstring_view wstr) noexcept { - try - { - const auto converted = ConvertToA(CP_UTF8, wstr); - return _Write(converted); - } - CATCH_RETURN(); + RETURN_IF_FAILED(til::u16u8(wstr, _conversionBuffer)); + return _Write(_conversionBuffer); } // Method Description: diff --git a/src/renderer/vt/tracing.cpp b/src/renderer/vt/tracing.cpp index ce3ec60bc..6d3adc53e 100644 --- a/src/renderer/vt/tracing.cpp +++ b/src/renderer/vt/tracing.cpp @@ -145,7 +145,7 @@ void RenderTracing::TraceInvalidateScroll(const til::point scroll) const } void RenderTracing::TraceStartPaint(const bool quickReturn, - const til::bitmap& invalidMap, + const til::pmr::bitmap& invalidMap, const til::rectangle lastViewport, const til::point scrollDelt, const bool cursorMoved, diff --git a/src/renderer/vt/tracing.hpp b/src/renderer/vt/tracing.hpp index 7d1cc7dfa..3a7675a79 100644 --- a/src/renderer/vt/tracing.hpp +++ b/src/renderer/vt/tracing.hpp @@ -39,7 +39,7 @@ namespace Microsoft::Console::VirtualTerminal void TraceTriggerCircling(const bool newFrame) const; void TraceInvalidateScroll(const til::point scroll) const; void TraceStartPaint(const bool quickReturn, - const til::bitmap& invalidMap, + const til::pmr::bitmap& invalidMap, const til::rectangle lastViewport, const til::point scrollDelta, const bool cursorMoved, diff --git a/src/renderer/vt/vtrenderer.hpp b/src/renderer/vt/vtrenderer.hpp index 9a9c81988..ad6c36d35 100644 --- a/src/renderer/vt/vtrenderer.hpp +++ b/src/renderer/vt/vtrenderer.hpp @@ -85,7 +85,7 @@ namespace Microsoft::Console::Render _Out_ FontInfo& Font, const int iDpi) noexcept override; - std::vector GetDirtyArea() override; + [[nodiscard]] HRESULT GetDirtyArea(gsl::span& area) noexcept override; [[nodiscard]] HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept override; [[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept override; @@ -113,12 +113,14 @@ namespace Microsoft::Console::Render std::string _buffer; std::string _formatBuffer; + std::string _conversionBuffer; TextAttribute _lastTextAttributes; Microsoft::Console::Types::Viewport _lastViewport; - til::bitmap _invalidMap; + std::pmr::unsynchronized_pool_resource _pool; + til::pmr::bitmap _invalidMap; COORD _lastText; til::point _scrollDelta; @@ -222,7 +224,7 @@ namespace Microsoft::Console::Render [[nodiscard]] HRESULT _WriteTerminalUtf8(const std::wstring_view str) noexcept; [[nodiscard]] HRESULT _WriteTerminalAscii(const std::wstring_view str) noexcept; - [[nodiscard]] virtual HRESULT _DoUpdateTitle(const std::wstring& newTitle) noexcept override; + [[nodiscard]] virtual HRESULT _DoUpdateTitle(const std::wstring_view newTitle) noexcept override; /////////////////////////// Unit Testing Helpers /////////////////////////// #ifdef UNIT_TESTING diff --git a/src/renderer/wddmcon/WddmConRenderer.cpp b/src/renderer/wddmcon/WddmConRenderer.cpp index d19aa5250..35415e53c 100644 --- a/src/renderer/wddmcon/WddmConRenderer.cpp +++ b/src/renderer/wddmcon/WddmConRenderer.cpp @@ -353,7 +353,7 @@ bool WddmConEngine::IsInitialized() return S_OK; } -std::vector WddmConEngine::GetDirtyArea() +[[nodiscard]] HRESULT WddmConEngine::GetDirtyArea(gsl::span& area) noexcept { SMALL_RECT r; r.Bottom = _displayHeight > 0 ? (SHORT)(_displayHeight - 1) : 0; @@ -361,7 +361,12 @@ std::vector WddmConEngine::GetDirtyArea() r.Left = 0; r.Right = _displayWidth > 0 ? (SHORT)(_displayWidth - 1) : 0; - return { r }; + _dirtyArea = r; + + area = { &_dirtyArea, + 1 }; + + return S_OK; } RECT WddmConEngine::GetDisplaySize() @@ -409,7 +414,7 @@ RECT WddmConEngine::GetDisplaySize() // - newTitle: the new string to use for the title of the window // Return Value: // - S_OK -[[nodiscard]] HRESULT WddmConEngine::_DoUpdateTitle(_In_ const std::wstring& /*newTitle*/) noexcept +[[nodiscard]] HRESULT WddmConEngine::_DoUpdateTitle(_In_ const std::wstring_view /*newTitle*/) noexcept { return S_OK; } diff --git a/src/renderer/wddmcon/WddmConRenderer.hpp b/src/renderer/wddmcon/WddmConRenderer.hpp index f9ad89b17..0d142be1b 100644 --- a/src/renderer/wddmcon/WddmConRenderer.hpp +++ b/src/renderer/wddmcon/WddmConRenderer.hpp @@ -59,12 +59,12 @@ namespace Microsoft::Console::Render [[nodiscard]] HRESULT GetProposedFont(const FontInfoDesired& fiFontInfoDesired, FontInfo& fiFontInfo, int const iDpi) noexcept override; - std::vector GetDirtyArea() override; + [[nodiscard]] HRESULT GetDirtyArea(gsl::span& area) noexcept override; [[nodiscard]] HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept override; [[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept override; protected: - [[nodiscard]] HRESULT _DoUpdateTitle(_In_ const std::wstring& newTitle) noexcept override; + [[nodiscard]] HRESULT _DoUpdateTitle(_In_ const std::wstring_view newTitle) noexcept override; private: HANDLE _hWddmConCtx; @@ -75,6 +75,7 @@ namespace Microsoft::Console::Render // Variables LONG _displayHeight; LONG _displayWidth; + til::rectangle _dirtyArea; PCD_IO_ROW_INFORMATION* _displayState;