From c174ba6a5690acc397eca572eb046c6aa6dec3da Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Fri, 18 Dec 2020 15:57:37 -0800 Subject: [PATCH] Use PMR allocator with a memory pool for PolyTextOut data since we're just going to use it again and again. --- src/inc/LibraryIncludes.h | 1 + src/renderer/gdi/gdirenderer.hpp | 7 +++++ src/renderer/gdi/paint.cpp | 45 ++++++++++++-------------------- src/renderer/gdi/state.cpp | 5 +++- 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/inc/LibraryIncludes.h b/src/inc/LibraryIncludes.h index 1e2510f0690..d8eee81b734 100644 --- a/src/inc/LibraryIncludes.h +++ b/src/inc/LibraryIncludes.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include diff --git a/src/renderer/gdi/gdirenderer.hpp b/src/renderer/gdi/gdirenderer.hpp index 28f745039cd..3be272c185d 100644 --- a/src/renderer/gdi/gdirenderer.hpp +++ b/src/renderer/gdi/gdirenderer.hpp @@ -125,6 +125,13 @@ namespace Microsoft::Console::Render COLORREF _lastBg; bool _lastFontItalic; + // Memory pooling to save alloc/free work to the OS for things + // frequently created and dropped. + // It's important the pool is first so it can be given to the others on construction. + std::pmr::unsynchronized_pool_resource _pool; + std::pmr::vector _polyStrings; + std::pmr::vector> _polyWidths; + [[nodiscard]] HRESULT _InvalidCombine(const RECT* const prc) noexcept; [[nodiscard]] HRESULT _InvalidOffset(const POINT* const ppt) noexcept; [[nodiscard]] HRESULT _InvalidRestrict() noexcept; diff --git a/src/renderer/gdi/paint.cpp b/src/renderer/gdi/paint.cpp index 1e07be9521f..74e0dd7bab8 100644 --- a/src/renderer/gdi/paint.cpp +++ b/src/renderer/gdi/paint.cpp @@ -298,6 +298,7 @@ using namespace Microsoft::Console::Render; { try { + const auto cchLine = clusters.size(); // Exit early if there are no lines to draw. @@ -308,14 +309,12 @@ using namespace Microsoft::Console::Render; const auto pPolyTextLine = &_pPolyText[_cPolyText]; - auto pwsPoly = std::make_unique(cchLine); - RETURN_IF_NULL_ALLOC(pwsPoly); + auto& polyString = _polyStrings.emplace_back(cchLine, UNICODE_NULL); COORD const coordFontSize = _GetFontSize(); - auto rgdxPoly = std::make_unique(cchLine); - RETURN_IF_NULL_ALLOC(rgdxPoly); - + auto& polyWidth = _polyWidths.emplace_back(cchLine, 0); + // Sum up the total widths the entire line/run is expected to take while // copying the pixel widths into a structure to direct GDI how many pixels to use per character. size_t cchCharWidths = 0; @@ -327,9 +326,9 @@ using namespace Microsoft::Console::Render; // Our GDI renderer hasn't and isn't going to handle things above U+FFFF or sequences. // So replace anything complicated with a replacement character for drawing purposes. - pwsPoly[i] = cluster.GetTextAsSingle(); - rgdxPoly[i] = gsl::narrow(cluster.GetColumns()) * coordFontSize.X; - cchCharWidths += rgdxPoly[i]; + polyString[i] = cluster.GetTextAsSingle(); + polyWidth[i] = gsl::narrow(cluster.GetColumns()) * coordFontSize.X; + cchCharWidths += polyWidth[i]; } // Detect and convert for raster font... @@ -338,7 +337,7 @@ using namespace Microsoft::Console::Render; // dispatch conversion into our codepage // Find out the bytes required - int const cbRequired = WideCharToMultiByte(_fontCodepage, 0, pwsPoly.get(), (int)cchLine, nullptr, 0, nullptr, nullptr); + int const cbRequired = WideCharToMultiByte(_fontCodepage, 0, polyString.data(), (int)cchLine, nullptr, 0, nullptr, nullptr); if (cbRequired != 0) { @@ -346,7 +345,7 @@ using namespace Microsoft::Console::Render; auto psConverted = std::make_unique(cbRequired); // Attempt conversion to current codepage - int const cbConverted = WideCharToMultiByte(_fontCodepage, 0, pwsPoly.get(), (int)cchLine, psConverted.get(), cbRequired, nullptr, nullptr); + int const cbConverted = WideCharToMultiByte(_fontCodepage, 0, polyString.data(), (int)cchLine, psConverted.get(), cbRequired, nullptr, nullptr); // If successful... if (cbConverted != 0) @@ -356,22 +355,22 @@ using namespace Microsoft::Console::Render; if (cchRequired != 0) { - auto pwsConvert = std::make_unique(cchRequired); + std::pmr::wstring polyConvert(cchRequired, UNICODE_NULL, &_pool); // Then do the actual conversion. - int const cchConverted = MultiByteToWideChar(CP_ACP, 0, psConverted.get(), cbRequired, pwsConvert.get(), cchRequired); + int const cchConverted = MultiByteToWideChar(CP_ACP, 0, psConverted.get(), cbRequired, polyConvert.data(), cchRequired); if (cchConverted != 0) { // If all successful, use this instead. - pwsPoly.swap(pwsConvert); + polyString.swap(polyConvert); } } } } } - pPolyTextLine->lpstr = pwsPoly.release(); + pPolyTextLine->lpstr = polyString.data(); pPolyTextLine->n = gsl::narrow(clusters.size()); pPolyTextLine->x = ptDraw.x; pPolyTextLine->y = ptDraw.y; @@ -380,7 +379,7 @@ using namespace Microsoft::Console::Render; pPolyTextLine->rcl.top = pPolyTextLine->y; pPolyTextLine->rcl.right = pPolyTextLine->rcl.left + ((SHORT)cchCharWidths * coordFontSize.X); pPolyTextLine->rcl.bottom = pPolyTextLine->rcl.top + coordFontSize.Y; - pPolyTextLine->pdx = rgdxPoly.release(); + pPolyTextLine->pdx = polyWidth.data(); if (trimLeft) { @@ -417,20 +416,10 @@ using namespace Microsoft::Console::Render; hr = E_FAIL; } - for (size_t iPoly = 0; iPoly < _cPolyText; iPoly++) - { - if (nullptr != _pPolyText[iPoly].lpstr) - { - delete[] _pPolyText[iPoly].lpstr; - _pPolyText[iPoly].lpstr = nullptr; - } + _polyStrings.clear(); + _polyWidths.clear(); - if (nullptr != _pPolyText[iPoly].pdx) - { - delete[] _pPolyText[iPoly].pdx; - _pPolyText[iPoly].pdx = nullptr; - } - } + ZeroMemory(_pPolyText, sizeof(_pPolyText)); _cPolyText = 0; } diff --git a/src/renderer/gdi/state.cpp b/src/renderer/gdi/state.cpp index fd03bb45ad4..807c503256b 100644 --- a/src/renderer/gdi/state.cpp +++ b/src/renderer/gdi/state.cpp @@ -32,7 +32,10 @@ GdiEngine::GdiEngine() : _lastFontItalic(false), _fPaintStarted(false), _hfont(nullptr), - _hfontItalic(nullptr) + _hfontItalic(nullptr), + _pool{}, // It's important the pool is first so it can be given to the others on construction. + _polyStrings{&_pool}, + _polyWidths{&_pool} { ZeroMemory(_pPolyText, sizeof(POLYTEXTW) * s_cPolyTextCache); _rcInvalid = { 0 };