Fix build errors, fix crashes, address comments

This commit is contained in:
Leonard Hecker 2021-10-29 03:19:20 +02:00
parent 8aef31b7ef
commit c1eccc99f1
28 changed files with 283 additions and 170 deletions

View file

@ -276,6 +276,41 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
## xxHash
**Source**: [https://github.com/Cyan4973/xxHash](https://github.com/Cyan4973/xxHash)
### License
```
xxHash Library
Copyright (c) 2012-2020 Yann Collet
All rights reserved.
BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
```
## ConEmu
**Source**: [https://github.com/Maximus5/ConEmu](https://github.com/Maximus5/ConEmu)

View file

@ -0,0 +1,3 @@
### Notes for Future Maintainers
At the time of writing xxHash (specifically XXH3) is only used in a modified form for the function `AtlasEngine::XXH3_len_32_64b`.

View file

@ -0,0 +1,13 @@
{"Registrations":[
{
"component": {
"type": "git",
"git": {
"repositoryUrl": "hhttps://github.com/Cyan4973/xxHash",
"commitHash": "9058687747c533a2fea7215fd72346e756da2034"
}
}
}
],
"Version": 1
}

View file

@ -483,7 +483,7 @@
ClearSettingValue="{x:Bind State.Profile.ClearUseAtlasEngine}"
HasSettingValue="{x:Bind State.Profile.HasUseAtlasEngine, Mode=OneWay}"
SettingOverrideSource="{x:Bind State.Profile.UseAtlasEngineOverrideSource, Mode=OneWay}"
Visibility="{x:Bind State.Profile.EditableUnfocusedAppearance}">
Visibility="{x:Bind State.Profile.AtlasEngineAvailable}">
<ToggleSwitch IsOn="{x:Bind State.Profile.UseAtlasEngine, Mode=TwoWay}" />
</local:SettingContainer>
</StackPanel>

View file

@ -125,7 +125,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
INHERITABLE_SETTING(Model::TerminalSettings, hstring, FontFace, DEFAULT_FONT_FACE);
INHERITABLE_SETTING(Model::TerminalSettings, int32_t, FontSize, DEFAULT_FONT_SIZE);
INHERITABLE_SETTING(Model::TerminalSettings, winrt::Windows::UI::Text::FontWeight, FontWeight, DEFAULT_FONT_WEIGHT);
INHERITABLE_SETTING(Model::TerminalSettings, winrt::Windows::UI::Text::FontWeight, FontWeight);
INHERITABLE_SETTING(Model::TerminalSettings, IFontAxesMap, FontAxes);
INHERITABLE_SETTING(Model::TerminalSettings, IFontFeatureMap, FontFeatures);

View file

@ -43,12 +43,12 @@
<ProjectReference Include="..\..\renderer\base\lib\base.vcxproj">
<Project>{af0a096a-8b3a-4949-81ef-7df8f0fee91f}</Project>
</ProjectReference>
<ProjectReference Include="..\..\renderer\dx\lib\dx.vcxproj">
<Project>{48d21369-3d7b-4431-9967-24e81292cf62}</Project>
</ProjectReference>
<ProjectReference Include="..\..\renderer\atlas\atlas.vcxproj">
<Project>{8222900C-8B6C-452A-91AC-BE95DB04B95F}</Project>
</ProjectReference>
<ProjectReference Include="..\..\renderer\dx\lib\dx.vcxproj">
<Project>{48d21369-3d7b-4431-9967-24e81292cf62}</Project>
</ProjectReference>
<ProjectReference Include="..\..\renderer\gdi\lib\gdi.vcxproj">
<Project>{1c959542-bac2-4e55-9a6d-13251914cbb9}</Project>
</ProjectReference>

View file

@ -38,6 +38,9 @@
<ProjectReference Include="..\..\renderer\base\lib\base.vcxproj">
<Project>{af0a096a-8b3a-4949-81ef-7df8f0fee91f}</Project>
</ProjectReference>
<ProjectReference Include="..\..\renderer\atlas\atlas.vcxproj">
<Project>{8222900C-8B6C-452A-91AC-BE95DB04B95F}</Project>
</ProjectReference>
<ProjectReference Include="..\..\renderer\dx\lib\dx.vcxproj">
<Project>{48d21369-3d7b-4431-9967-24e81292cf62}</Project>
</ProjectReference>
@ -71,6 +74,7 @@
<AdditionalIncludeDirectories>..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>

View file

@ -2320,9 +2320,6 @@ void ReadStringWithReadConsoleInputAHelper(HANDLE hIn, PCSTR pszExpectedText, si
while (cchRead < cchExpectedText)
{
// expected read is either the size of the buffer or the number of characters remaining, whichever is smaller.
DWORD const dwReadExpected = (DWORD)std::min(cbBuffer, cchExpectedText - cchRead);
DWORD dwRead;
if (!VERIFY_WIN32_BOOL_SUCCEEDED(ReadConsoleInputA(hIn, irRead, (DWORD)cbBuffer, &dwRead), L"Attempt to read input into buffer."))
{

View file

@ -274,7 +274,8 @@ void ApiRoutines::GetNumberOfConsoleMouseButtonsImpl(ULONG& buttons) noexcept
const FontInfo& fontInfo = activeScreenInfo.GetCurrentFont();
consoleFontInfoEx.FontFamily = fontInfo.GetFamily();
consoleFontInfoEx.FontWeight = fontInfo.GetWeight();
fontInfo.FillLegacyNameBuffer(consoleFontInfoEx.FaceName);
RETURN_IF_FAILED(fontInfo.FillLegacyNameBuffer(gsl::make_span(consoleFontInfoEx.FaceName)));
return S_OK;
}

View file

@ -255,14 +255,6 @@ void Selection::ExtendSelection(_In_ COORD coordBufferPos)
srNewSelection.Top = _coordSelectionAnchor.Y;
}
// This function is called on WM_MOUSEMOVE.
// Prevent triggering an invalidation just because the mouse moved
// in the same cell without changing the actual (visible) selection.
if (_srSelectionRect == srNewSelection)
{
return;
}
// call special update method to modify the displayed selection in-place
// NOTE: Using HideSelection, editing the rectangle, then ShowSelection will cause flicker.
//_PaintUpdateSelection(&srNewSelection);

View file

@ -815,7 +815,9 @@ void Settings::SetTerminalScrolling(const bool terminalScrollingEnabled) noexcep
// - Determines whether our primary renderer should be DirectX or GDI.
// - This is based on user preference and velocity hold back state.
// Return Value:
// - True means use DirectX renderer. False means use GDI renderer.
// - case 1: DxEngine
// - case 2: AtlasEngine
// - default: GdiEngine
DWORD Settings::GetUseDx() const noexcept
{
return _fUseDx;

View file

@ -52,6 +52,9 @@
<ProjectReference Include="..\..\internal\internal.vcxproj">
<Project>{ef3e32a7-5ff6-42b4-b6e2-96cd7d033f00}</Project>
</ProjectReference>
<ProjectReference Include="..\..\renderer\atlas\atlas.vcxproj">
<Project>{8222900C-8B6C-452A-91AC-BE95DB04B95F}</Project>
</ProjectReference>
<ProjectReference Include="..\..\renderer\dx\lib\dx.vcxproj">
<Project>{48d21369-3d7b-4431-9967-24e81292cf62}</Project>
</ProjectReference>

View file

@ -22,6 +22,9 @@
<ProjectReference Include="..\..\..\internal\internal.vcxproj">
<Project>{ef3e32a7-5ff6-42b4-b6e2-96cd7d033f00}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\renderer\atlas\atlas.vcxproj">
<Project>{8222900C-8B6C-452A-91AC-BE95DB04B95F}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\renderer\dx\lib\dx.vcxproj">
<Project>{48d21369-3d7b-4431-9967-24e81292cf62}</Project>
</ProjectReference>
@ -76,4 +79,4 @@
<!-- Careful reordering these. Some default props (contained in these files) are order sensitive. -->
<Import Project="$(SolutionDir)src\common.build.post.props" />
<Import Project="$(SolutionDir)src\common.build.tests.props" />
</Project>
</Project>

View file

@ -735,7 +735,6 @@ class UiaTextRangeTests
TEST_METHOD(CanMoveByCharacter)
{
const SHORT lastColumnIndex = _pScreenInfo->GetBufferSize().RightInclusive();
const SHORT bottomRow = gsl::narrow<SHORT>(_pTextBuffer->TotalRowCount() - 1);
// GH#6986: This is used as the "end of the buffer" to help screen readers run faster
// instead of parsing through thousands of empty lines of text.
@ -824,7 +823,6 @@ class UiaTextRangeTests
TEST_METHOD(CanMoveByLine)
{
const SHORT lastColumnIndex = _pScreenInfo->GetBufferSize().Width() - 1;
const SHORT bottomRow = gsl::narrow<SHORT>(_pTextBuffer->TotalRowCount() - 1);
// GH#6986: This is used as the "end of the buffer" to help screen readers run faster
// instead of parsing through thousands of empty lines of text.
@ -913,7 +911,6 @@ class UiaTextRangeTests
TEST_METHOD(CanMoveEndpointByUnitCharacter)
{
const SHORT lastColumnIndex = _pScreenInfo->GetBufferSize().Width() - 1;
const SHORT bottomRow = static_cast<SHORT>(_pTextBuffer->TotalRowCount() - 1);
// GH#6986: This is used as the "end of the buffer" to help screen readers run faster
// instead of parsing through thousands of empty lines of text.
@ -1197,7 +1194,6 @@ class UiaTextRangeTests
TEST_METHOD(CanMoveEndpointByUnitDocument)
{
const SHORT lastColumnIndex = _pScreenInfo->GetBufferSize().Width() - 1;
const SHORT bottomRow = gsl::narrow<SHORT>(_pTextBuffer->TotalRowCount() - 1);
// GH#6986: This is used as the "end of the buffer" to help screen readers run faster

View file

@ -26,8 +26,10 @@
#include "../../renderer/base/renderer.hpp"
#include "../../renderer/gdi/gdirenderer.hpp"
#if TIL_FEATURE_CONHOSTDXENGINE_ENABLED
#if TIL_FEATURE_ATLASENGINE_ENABLED
#include "../../renderer/atlas/AtlasEngine.h"
#endif
#if TIL_FEATURE_CONHOSTDXENGINE_ENABLED
#include "../../renderer/dx/DxRenderer.hpp"
#endif
@ -211,6 +213,8 @@ void Window::_UpdateSystemMetrics() const
GdiEngine* pGdiEngine = nullptr;
#if TIL_FEATURE_CONHOSTDXENGINE_ENABLED
DxEngine* pDxEngine = nullptr;
#endif
#if TIL_FEATURE_ATLASENGINE_ENABLED
AtlasEngine* pAtlasEngine = nullptr;
#endif
try
@ -228,6 +232,8 @@ void Window::_UpdateSystemMetrics() const
THROW_IF_FAILED(pDxEngine->SetHwnd(nullptr));
g.pRender->AddRenderEngine(pDxEngine);
break;
#endif
#if TIL_FEATURE_ATLASENGINE_ENABLED
case 2:
pAtlasEngine = new AtlasEngine();
g.pRender->AddRenderEngine(pAtlasEngine);
@ -333,7 +339,10 @@ void Window::_UpdateSystemMetrics() const
status = NTSTATUS_FROM_WIN32(HRESULT_CODE((pDxEngine->Enable())));
}
}
else if (pAtlasEngine)
else
#endif
#if TIL_FEATURE_ATLASENGINE_ENABLED
if (pAtlasEngine)
{
status = NTSTATUS_FROM_WIN32(HRESULT_CODE((pAtlasEngine->SetHwnd(hWnd))));
}

View file

@ -40,7 +40,7 @@ constexpr HRESULT vec2_narrow(U x, U y, AtlasEngine::vec2<T>& out) noexcept
[[nodiscard]] HRESULT AtlasEngine::Invalidate(const SMALL_RECT* const psrRegion) noexcept
{
assert(psrRegion->Top <= psrRegion->Bottom && psrRegion->Top >= 0 && psrRegion->Bottom <= _api.cellCount.y);
assert(psrRegion->Top < psrRegion->Bottom && psrRegion->Top >= 0 && psrRegion->Bottom <= _api.cellCount.y);
// BeginPaint() protects against invalid out of bounds numbers.
_api.invalidatedRows.x = std::min(_api.invalidatedRows.x, gsl::narrow_cast<u16>(psrRegion->Top));
@ -173,10 +173,24 @@ constexpr HRESULT vec2_narrow(U x, U y, AtlasEngine::vec2<T>& out) noexcept
[[nodiscard]] HRESULT AtlasEngine::GetProposedFont(const FontInfoDesired& fontInfoDesired, _Out_ FontInfo& fontInfo, const int dpi) noexcept
try
{
const auto& requestedFaceName = fontInfoDesired.GetFaceName();
const wchar_t* requestedFaceName = fontInfoDesired.GetFaceName().data();
const auto requestedFamily = fontInfoDesired.GetFamily();
const auto requestedWeight = fontInfoDesired.GetWeight();
const auto requestedSize = fontInfoDesired.GetEngineSize();
auto requestedWeight = fontInfoDesired.GetWeight();
auto requestedSize = fontInfoDesired.GetEngineSize();
if (!requestedFaceName)
{
requestedFaceName = L"Consolas";
}
if (!requestedWeight)
{
requestedWeight = DWRITE_FONT_WEIGHT_NORMAL;
}
if (!requestedSize.Y)
{
requestedSize = { 0, 16 };
}
std::wstring faceNameBuffer;
std::wstring_view resultingFaceName = requestedFaceName;
COORD resultingCellSize{};
@ -237,7 +251,7 @@ try
#endif
{
wil::com_ptr<IDWriteTextFormat> textFormat;
THROW_IF_FAILED(_createTextFormat(requestedFaceName.c_str(), static_cast<DWRITE_FONT_WEIGHT>(requestedWeight), DWRITE_FONT_STYLE_NORMAL, requestedSize.Y, textFormat.addressof()));
THROW_IF_FAILED(_createTextFormat(requestedFaceName, static_cast<DWRITE_FONT_WEIGHT>(requestedWeight), DWRITE_FONT_STYLE_NORMAL, requestedSize.Y, textFormat.addressof()));
wil::com_ptr<IDWriteTextLayout> textLayout;
THROW_IF_FAILED(_sr.dwriteFactory->CreateTextLayout(L"M", 1, textFormat.get(), FLT_MAX, FLT_MAX, textLayout.addressof()));

View file

@ -4,6 +4,7 @@
#include "pch.h"
#include "AtlasEngine.h"
#include <dxgidebug.h>
#include <til/bit.h>
#include <shader_ps.h>
@ -48,6 +49,17 @@ struct TextAnalyzer final : IDWriteTextAnalysisSource, IDWriteTextAnalysisSink
Ensures(_text.size() <= UINT32_MAX);
}
#ifndef NDEBUG
private:
ULONG _refCount = 1;
public:
~TextAnalyzer()
{
assert(_refCount == 1);
}
#endif
HRESULT __stdcall QueryInterface(const IID& riid, void** ppvObject) noexcept override
{
__assume(ppvObject != nullptr);
@ -64,14 +76,20 @@ struct TextAnalyzer final : IDWriteTextAnalysisSource, IDWriteTextAnalysisSink
ULONG __stdcall AddRef() noexcept override
{
assert(false);
#ifdef NDEBUG
return 1;
#else
return ++_refCount;
#endif
}
ULONG __stdcall Release() noexcept override
{
assert(false);
#ifdef NDEBUG
return 1;
#else
return --_refCount;
#endif
}
HRESULT __stdcall GetTextAtPosition(UINT32 textPosition, const WCHAR** textString, UINT32* textLength) noexcept override
@ -209,18 +227,19 @@ try
}
WI_ClearAllFlags(_invalidations, InvalidationFlags::device | InvalidationFlags::size | InvalidationFlags::font | InvalidationFlags::settings);
std::ignore = InvalidateAll();
_api.invalidatedRows = invalidatedRowsAll;
}
// Clamp invalidation rects into valid value ranges.
if (_api.invalidatedRows == invalidatedRowsAll)
{
// Skip all the partial updates, since we redraw everything anyways.
_api.invalidatedCursorArea = invalidatedAreaNone;
_api.invalidatedRows = { 0, _api.cellCount.y };
_api.scrollOffset = 0;
}
else
{
// Clamp invalidation rects into valid value ranges.
{
_api.invalidatedCursorArea.left = std::min(_api.invalidatedCursorArea.left, _api.cellCount.x);
_api.invalidatedCursorArea.top = std::min(_api.invalidatedCursorArea.top, _api.cellCount.y);
@ -235,49 +254,49 @@ try
const auto limit = gsl::narrow_cast<i16>(_api.cellCount.y & 0x7fff);
_api.scrollOffset = clamp<i16>(_api.scrollOffset, -limit, limit);
}
}
// Scroll the buffer by the given offset and mark the newly uncovered rows as "invalid".
if (_api.scrollOffset != 0)
{
const auto data = _r.cells.data();
auto count = _r.cells.size();
const auto offset = static_cast<ptrdiff_t>(_api.scrollOffset) * _api.cellCount.x;
Cell* dst;
Cell* src;
if (_api.scrollOffset < 0)
// Scroll the buffer by the given offset and mark the newly uncovered rows as "invalid".
if (_api.scrollOffset != 0)
{
// Scroll up (for instance when new text is being written at the end of the buffer).
dst = data;
src = data - offset;
count += offset;
_api.invalidatedRows.x = std::min<u16>(_api.invalidatedRows.x, _api.cellCount.y + _api.scrollOffset);
_api.invalidatedRows.y = _api.cellCount.y;
}
else
{
// Scroll down.
dst = data + offset;
src = data;
count -= offset;
_api.invalidatedRows.x = 0;
_api.invalidatedRows.y = std::max<u16>(_api.invalidatedRows.y, _api.scrollOffset);
}
const auto nothingInvalid = _api.invalidatedRows.x == _api.invalidatedRows.y;
const auto offset = static_cast<ptrdiff_t>(_api.scrollOffset) * _api.cellCount.x;
const auto data = _r.cells.data();
auto count = _r.cells.size();
Cell* dst;
Cell* src;
memmove(dst, src, count * sizeof(Cell));
if (_api.scrollOffset < 0)
{
// Scroll up (for instance when new text is being written at the end of the buffer).
dst = data;
src = data - offset;
count += offset;
const u16 endRow = _api.cellCount.y + _api.scrollOffset;
_api.invalidatedRows.x = nothingInvalid ? endRow : std::min<u16>(_api.invalidatedRows.x, endRow);
_api.invalidatedRows.y = _api.cellCount.y;
}
else
{
// Scroll down.
dst = data + offset;
src = data;
count -= offset;
_api.invalidatedRows.x = 0;
_api.invalidatedRows.y = nothingInvalid ? _api.scrollOffset : std::max<u16>(_api.invalidatedRows.y, _api.scrollOffset);
}
memmove(dst, src, count * sizeof(Cell));
}
}
{
// _api.dirtyRect is an inclusive rectangle, whereas _api.invalidatedRows is an exclusive range.
// --> We need to subtract 1 from the bottom row index.
// However .x could be equal to .y (for instance both could be 0), so we
// need to ensure top isn't greater than bottom after the subtraction.
const auto right = static_cast<ptrdiff_t>(_api.cellCount.x);
const auto bottom = static_cast<ptrdiff_t>(_api.invalidatedRows.y);
const auto top = static_cast<ptrdiff_t>(_api.invalidatedRows.x);
_api.dirtyRect = til::rectangle{ 0u, top, right, bottom };
}
_api.dirtyRect = til::rectangle{
static_cast<ptrdiff_t>(0),
static_cast<ptrdiff_t>(_api.invalidatedRows.x),
static_cast<ptrdiff_t>(_api.cellCount.x),
static_cast<ptrdiff_t>(_api.invalidatedRows.y),
};
return S_OK;
}
@ -411,7 +430,7 @@ try
// # What do we want?
//
// Segment a line of text (_api.bufferLine) into unicode "clusters".
// Each cluster is one "whole" glyph with diacritics, ligatures, zero-width-joiners
// Each cluster is one "whole" glyph with diacritics, ligatures, zero width joiners
// and whatever else, that should be cached as a whole in our texture atlas.
//
// # How do we get that?
@ -425,7 +444,7 @@ try
//
// ## The actual approach
//
// DirectWrite has 2 APIs which can segment text properly (including ligatures and zero width joiner for instance):
// DirectWrite has 2 APIs which can segment text properly (including ligatures and zero width joiners):
// * IDWriteTextAnalyzer1::GetTextComplexity
// * IDWriteTextAnalyzer::GetGlyphs
//
@ -619,57 +638,6 @@ CATCH_RETURN()
#pragma endregion
#pragma region Helper classes
// XXH3 for exactly 32 bytes.
uint64_t AtlasEngine::XXH3_len_32_64b(const void* data) noexcept
{
static constexpr uint64_t dataSize = 32;
static constexpr auto XXH3_mul128_fold64 = [](uint64_t lhs, uint64_t rhs) noexcept {
uint64_t lo, hi;
#if defined(_M_AMD64)
lo = _umul128(lhs, rhs, &hi);
#elif defined(_M_ARM64)
lo = lhs * rhs;
hi = __umulh(lhs, rhs);
#else
const uint64_t lo_lo = __emulu(lhs, rhs);
const uint64_t hi_lo = __emulu(lhs >> 32, rhs);
const uint64_t lo_hi = __emulu(lhs, rhs >> 32);
const uint64_t hi_hi = __emulu(lhs >> 32, rhs >> 32);
const uint64_t cross = (lo_lo >> 32) + (hi_lo & 0xFFFFFFFF) + lo_hi;
hi = (hi_lo >> 32) + (cross >> 32) + hi_hi;
lo = (cross << 32) | (lo_lo & 0xFFFFFFFF);
#endif
return lo ^ hi;
};
// If executed on little endian CPUs these 4 numbers will
// equal the first 32 byte of the original XXH3_kSecret.
static constexpr uint64_t XXH3_kSecret[4] = {
UINT64_C(0xbe4ba423396cfeb8),
UINT64_C(0x1cad21f72c81017c),
UINT64_C(0xdb979083e96dd4de),
UINT64_C(0x1f67b3b7a4a44072),
};
uint64_t inputs[4];
memcpy(&inputs[0], data, 32);
#pragma warning(suppress : 26450) // Arithmetic overflow: '*' operation causes overflow at compile time. Use a wider type to store the operands (io.1).
uint64_t acc = dataSize * UINT64_C(0x9E3779B185EBCA87);
acc += XXH3_mul128_fold64(inputs[0] ^ XXH3_kSecret[0], inputs[1] ^ XXH3_kSecret[1]);
acc += XXH3_mul128_fold64(inputs[2] ^ XXH3_kSecret[2], inputs[3] ^ XXH3_kSecret[3]);
acc = acc ^ (acc >> 37);
acc *= UINT64_C(0x165667919E3779F9);
acc = acc ^ (acc >> 32);
return acc;
}
#pragma endregion
[[nodiscard]] HRESULT AtlasEngine::_handleException(const wil::ResultException& exception) noexcept
{
const auto hr = exception.GetErrorCode();
@ -696,21 +664,25 @@ void AtlasEngine::_createResources()
#ifndef NDEBUG
// DXGI debug messages + enabling D3D11_CREATE_DEVICE_DEBUG if the Windows SDK was installed.
if (const wil::unique_hmodule module{ LoadLibraryExW(L"dxgidebug.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32) })
if (const wil::unique_hmodule module{ LoadLibraryExW(L"dxgi.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32) })
{
deviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
const auto DXGIGetDebugInterface = reinterpret_cast<HRESULT(WINAPI*)(REFIID, void**)>(GetProcAddress(module.get(), "DXGIGetDebugInterface"));
THROW_LAST_ERROR_IF(!DXGIGetDebugInterface);
wil::com_ptr<IDXGIInfoQueue> infoQueue;
if (SUCCEEDED(DXGIGetDebugInterface(IID_PPV_ARGS(infoQueue.addressof()))))
if (const auto DXGIGetDebugInterface1 = GetProcAddressByFunctionDeclaration(module.get(), DXGIGetDebugInterface1))
{
// I didn't want to link with dxguid.lib just for getting DXGI_DEBUG_ALL. This GUID is publicly documented.
static constexpr GUID dxgiDebguAll = { 0xe48ae283, 0xda80, 0x490b, { 0x87, 0xe6, 0x43, 0xe9, 0xa9, 0xcf, 0xda, 0x8 } };
for (const auto severity : std::array{ DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_WARNING })
if (wil::com_ptr<IDXGIInfoQueue> infoQueue; SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(infoQueue.addressof()))))
{
infoQueue->SetBreakOnSeverity(dxgiDebguAll, severity, true);
// I didn't want to link with dxguid.lib just for getting DXGI_DEBUG_ALL. This GUID is publicly documented.
static constexpr GUID dxgiDebugAll = { 0xe48ae283, 0xda80, 0x490b, { 0x87, 0xe6, 0x43, 0xe9, 0xa9, 0xcf, 0xda, 0x8 } };
for (const auto severity : std::array{ DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_WARNING })
{
infoQueue->SetBreakOnSeverity(dxgiDebugAll, severity, true);
}
}
if (wil::com_ptr<IDXGIDebug1> debug; SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(debug.addressof()))))
{
debug->EnableLeakTrackingForThread();
}
}
}

View file

@ -105,6 +105,7 @@ namespace Microsoft::Console::Render
constexpr vec2 operator/(const vec2& rhs) noexcept
{
assert(rhs.x != 0 && rhs.y != 0);
return { gsl::narrow_cast<T>(x / rhs.x), gsl::narrow_cast<T>(y / rhs.y) };
}
};
@ -409,7 +410,7 @@ namespace Microsoft::Console::Render
wil::unique_process_heap_string fontName; // changes are flagged as InvalidationFlags::font|size
u16 fontSize = 0; // changes are flagged as InvalidationFlags::font|size
u16 fontWeight = DWRITE_FONT_WEIGHT_NORMAL; // changes are flagged as InvalidationFlags::font
u16 fontWeight = 0; // changes are flagged as InvalidationFlags::font
u16 dpi = USER_DEFAULT_SCREEN_DPI; // changes are flagged as InvalidationFlags::font|size
u16 antialiasingMode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE; // changes are flagged as InvalidationFlags::font

View file

@ -0,0 +1,57 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "AtlasEngine.h"
using namespace Microsoft::Console::Render;
// XXH3 for exactly 32 bytes.
uint64_t AtlasEngine::XXH3_len_32_64b(const void* data) noexcept
{
static constexpr uint64_t dataSize = 32;
static constexpr auto XXH3_mul128_fold64 = [](uint64_t lhs, uint64_t rhs) noexcept {
uint64_t lo, hi;
#if defined(_M_AMD64)
lo = _umul128(lhs, rhs, &hi);
#elif defined(_M_ARM64)
lo = lhs * rhs;
hi = __umulh(lhs, rhs);
#else
// Implemented as a macro as MSVC tends to call __allmul otherwise.
#define XXH_mult32to64(x, y) __emulu(gsl::narrow_cast<uint32_t>(x), gsl::narrow_cast<uint32_t>(y))
const uint64_t lo_lo = XXH_mult32to64(lhs, rhs);
const uint64_t hi_lo = XXH_mult32to64(lhs >> 32, rhs);
const uint64_t lo_hi = XXH_mult32to64(lhs, rhs >> 32);
const uint64_t hi_hi = XXH_mult32to64(lhs >> 32, rhs >> 32);
const uint64_t cross = (lo_lo >> 32) + (hi_lo & 0xFFFFFFFF) + lo_hi;
hi = (hi_lo >> 32) + (cross >> 32) + hi_hi;
lo = (cross << 32) | (lo_lo & 0xFFFFFFFF);
#undef XXH_mult32to64
#endif
return lo ^ hi;
};
// If executed on little endian CPUs these 4 numbers will
// equal the first 32 byte of the original XXH3_kSecret.
static constexpr uint64_t XXH3_kSecret[4] = {
UINT64_C(0xbe4ba423396cfeb8),
UINT64_C(0x1cad21f72c81017c),
UINT64_C(0xdb979083e96dd4de),
UINT64_C(0x1f67b3b7a4a44072),
};
uint64_t inputs[4];
memcpy(&inputs[0], data, 32);
#pragma warning(suppress : 26450) // Arithmetic overflow: '*' operation causes overflow at compile time. Use a wider type to store the operands (io.1).
uint64_t acc = dataSize * UINT64_C(0x9E3779B185EBCA87);
acc += XXH3_mul128_fold64(inputs[0] ^ XXH3_kSecret[0], inputs[1] ^ XXH3_kSecret[1]);
acc += XXH3_mul128_fold64(inputs[2] ^ XXH3_kSecret[2], inputs[3] ^ XXH3_kSecret[3]);
acc = acc ^ (acc >> 37);
acc *= UINT64_C(0x165667919E3779F9);
acc = acc ^ (acc >> 32);
return acc;
}

View file

@ -12,6 +12,7 @@
<ItemGroup>
<ClCompile Include="AtlasEngine.api.cpp" />
<ClCompile Include="AtlasEngine.r.cpp" />
<ClCompile Include="AtlasEngine.xxh.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>

View file

@ -43,7 +43,7 @@ FontInfoBase::~FontInfoBase()
{
}
unsigned char FontInfoBase::GetFamily() const noexcept
unsigned char FontInfoBase::GetFamily() const
{
return _family;
}
@ -51,22 +51,22 @@ unsigned char FontInfoBase::GetFamily() const noexcept
// When the default raster font is forced set from the engine, this is how we differentiate it from a simple apply.
// Default raster font is internally represented as a blank face name and zeros for weight, family, and size. This is
// the hint for the engine to use whatever comes back from GetStockObject(OEM_FIXED_FONT) (at least in the GDI world).
bool FontInfoBase::WasDefaultRasterSetFromEngine() const noexcept
bool FontInfoBase::WasDefaultRasterSetFromEngine() const
{
return _fDefaultRasterSetFromEngine;
}
unsigned int FontInfoBase::GetWeight() const noexcept
unsigned int FontInfoBase::GetWeight() const
{
return _weight;
}
const std::wstring& FontInfoBase::GetFaceName() const noexcept
const std::wstring_view FontInfoBase::GetFaceName() const noexcept
{
return _faceName;
}
unsigned int FontInfoBase::GetCodePage() const noexcept
unsigned int FontInfoBase::GetCodePage() const
{
return _codePage;
}
@ -77,7 +77,7 @@ unsigned int FontInfoBase::GetCodePage() const noexcept
// Arguments:
// - buffer: the buffer into which to copy characters
// - size: the size of buffer
HRESULT FontInfoBase::FillLegacyNameBuffer(gsl::span<wchar_t> buffer) const noexcept
HRESULT FontInfoBase::FillLegacyNameBuffer(gsl::span<wchar_t> buffer) const
try
{
auto toCopy = std::min<size_t>(buffer.size() - 1, _faceName.size());
@ -91,7 +91,7 @@ CATCH_RETURN();
void FontInfoBase::SetFromEngine(const std::wstring_view faceName,
const unsigned char family,
const unsigned int weight,
const bool fSetDefaultRasterFont) noexcept
const bool fSetDefaultRasterFont)
{
_faceName = faceName;
_family = family;
@ -101,12 +101,12 @@ void FontInfoBase::SetFromEngine(const std::wstring_view faceName,
// Internally, default raster font is represented by empty facename, and zeros for weight, family, and size. Since
// FontInfoBase doesn't have sizing information, this helper checks everything else.
bool FontInfoBase::IsDefaultRasterFontNoSize() const noexcept
bool FontInfoBase::IsDefaultRasterFontNoSize() const
{
return (_weight == 0 && _family == 0 && _faceName.empty());
}
void FontInfoBase::ValidateFont() noexcept
void FontInfoBase::ValidateFont()
{
// If we were given a blank name, it meant raster fonts, which to us is always Terminal.
if (!IsDefaultRasterFontNoSize() && s_pFontDefaultList != nullptr)
@ -128,7 +128,7 @@ void FontInfoBase::ValidateFont() noexcept
}
}
bool FontInfoBase::IsTrueTypeFont() const noexcept
bool FontInfoBase::IsTrueTypeFont() const
{
return WI_IsFlagSet(_family, TMPF_TRUETYPE);
}

View file

@ -11,7 +11,7 @@ bool operator==(const FontInfoDesired& a, const FontInfoDesired& b)
a._coordSizeDesired == b._coordSizeDesired);
}
COORD FontInfoDesired::GetEngineSize() const noexcept
COORD FontInfoDesired::GetEngineSize() const
{
COORD coordSize = _coordSizeDesired;
if (IsTrueTypeFont())
@ -41,7 +41,7 @@ FontInfoDesired::FontInfoDesired(const FontInfo& fiFont) :
// This helper determines if this object represents the default raster font. This can either be because internally we're
// using the empty facename and zeros for size, weight, and family, or it can be because we were given explicit
// dimensions from the engine that were the result of loading the default raster font. See GdiEngine::_GetProposedFont().
bool FontInfoDesired::IsDefaultRasterFont() const noexcept
bool FontInfoDesired::IsDefaultRasterFont() const
{
// Either the raster was set from the engine...
// OR the face name is empty with a size of 0x0 or 8x12.

View file

@ -33,12 +33,12 @@ FontInfo::FontInfo(const FontInfo& fiFont) :
{
}
COORD FontInfo::GetUnscaledSize() const noexcept
COORD FontInfo::GetUnscaledSize() const
{
return _coordSizeUnscaled;
}
COORD FontInfo::GetSize() const noexcept
COORD FontInfo::GetSize() const
{
return _coordSize;
}
@ -48,7 +48,7 @@ void FontInfo::SetFromEngine(const std::wstring_view faceName,
const unsigned int weight,
const bool fSetDefaultRasterFont,
const COORD coordSize,
const COORD coordSizeUnscaled) noexcept
const COORD coordSizeUnscaled)
{
FontInfoBase::SetFromEngine(faceName,
family,

View file

@ -1253,7 +1253,12 @@ std::vector<SMALL_RECT> Renderer::_GetSelectionRects() const
const auto lineRendition = buffer.GetLineRendition(rect.Top());
rect = Viewport::FromInclusive(BufferToScreenLine(rect.ToInclusive(), lineRendition));
auto sr = view.ConvertToOrigin(rect).ToExclusive();
auto sr = view.ConvertToOrigin(rect).ToInclusive();
// hopefully temporary, we should be receiving the right selection sizes without correction.
sr.Right++;
sr.Bottom++;
result.emplace_back(sr);
}

View file

@ -8,6 +8,7 @@
#include "../../interactivity/win32/CustomWindowMessages.h"
#include "../../types/inc/Viewport.hpp"
#include "../../inc/unicode.hpp"
#include "../../inc/DefaultSettings.h"
#include <VersionHelpers.h>
@ -15,12 +16,11 @@
#include "ScreenVertexShader.h"
#include <DirectXMath.h>
#include <d3dcompiler.h>
#include <DirectXColors.h>
using namespace DirectX;
using namespace Microsoft::Console::Render;
using namespace Microsoft::Console::Types;
std::atomic<size_t> DxEngine::_tracelogCount{ 0 };
std::atomic<size_t> Microsoft::Console::Render::DxEngine::_tracelogCount{ 0 };
#pragma warning(suppress : 26477) // We don't control tracelogging macros
TRACELOGGING_DEFINE_PROVIDER(g_hDxRenderProvider,
"Microsoft.Windows.Terminal.Renderer.DirectX",
@ -49,6 +49,11 @@ D3D11_INPUT_ELEMENT_DESC _shaderInputLayout[] = {
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }
};
#pragma hdrstop
using namespace Microsoft::Console::Render;
using namespace Microsoft::Console::Types;
// Routine Description:
// - Constructs a DirectX-based renderer for console text
// which primarily uses DirectWrite on a Direct2D surface

View file

@ -37,15 +37,15 @@ public:
FontInfo(const FontInfo& fiFont);
COORD GetSize() const noexcept;
COORD GetUnscaledSize() const noexcept;
COORD GetSize() const;
COORD GetUnscaledSize() const;
void SetFromEngine(const std::wstring_view faceName,
const unsigned char family,
const unsigned int weight,
const bool fSetDefaultRasterFont,
const COORD coordSize,
const COORD coordSizeUnscaled) noexcept;
const COORD coordSizeUnscaled);
bool GetFallback() const noexcept;
void SetFallback(const bool didFallback) noexcept;

View file

@ -36,22 +36,22 @@ public:
~FontInfoBase();
unsigned char GetFamily() const noexcept;
unsigned int GetWeight() const noexcept;
const std::wstring& GetFaceName() const noexcept;
unsigned int GetCodePage() const noexcept;
unsigned char GetFamily() const;
unsigned int GetWeight() const;
const std::wstring_view GetFaceName() const noexcept;
unsigned int GetCodePage() const;
HRESULT FillLegacyNameBuffer(gsl::span<wchar_t> buffer) const noexcept;
HRESULT FillLegacyNameBuffer(gsl::span<wchar_t> buffer) const;
bool IsTrueTypeFont() const noexcept;
bool IsTrueTypeFont() const;
void SetFromEngine(const std::wstring_view faceName,
const unsigned char family,
const unsigned int weight,
const bool fSetDefaultRasterFont) noexcept;
const bool fSetDefaultRasterFont);
bool WasDefaultRasterSetFromEngine() const noexcept;
void ValidateFont() noexcept;
bool WasDefaultRasterSetFromEngine() const;
void ValidateFont();
static Microsoft::Console::Render::IFontDefaultList* s_pFontDefaultList;
static void s_SetFontDefaultList(_In_ Microsoft::Console::Render::IFontDefaultList* const pFontDefaultList);
@ -59,7 +59,7 @@ public:
friend bool operator==(const FontInfoBase& a, const FontInfoBase& b);
protected:
bool IsDefaultRasterFontNoSize() const noexcept;
bool IsDefaultRasterFontNoSize() const;
private:
std::wstring _faceName;

View file

@ -32,8 +32,8 @@ public:
FontInfoDesired(const FontInfo& fiFont);
COORD GetEngineSize() const noexcept;
bool IsDefaultRasterFont() const noexcept;
COORD GetEngineSize() const;
bool IsDefaultRasterFont() const;
friend bool operator==(const FontInfoDesired& a, const FontInfoDesired& b);